@@ -29,22 +29,12 @@ public override string ToString()
2929
3030public class IUnknownMarshalingTest
3131{
32- [ DllImport ( @"IUnknownNative" , CallingConvention = CallingConvention . Cdecl ) ]
33- private static extern bool Marshal_IUnknown ( [ In ] IntPtr ptr ) ;
34-
3532 private object [ ] TestObjects ;
3633
37- public void GetIUnknownForObjectTest ( )
34+ public unsafe void GetIUnknownForObjectTest ( )
3835 {
39-
40- try
41- {
42- //test null
43- IntPtr nullPtr = Marshal . GetIUnknownForObject ( null ) ;
44- }
45- catch ( ArgumentNullException ) { }
46-
47-
36+ // Test null
37+ Assert . Throws < ArgumentNullException > ( ( ) => Marshal . GetIUnknownForObject ( null ) ) ;
4838 foreach ( object obj in TestObjects )
4939 {
5040 IntPtr ptr = IntPtr . Zero ;
@@ -53,82 +43,36 @@ public void GetIUnknownForObjectTest()
5343 {
5444 ptr = Marshal . GetIUnknownForObject ( obj ) ;
5545
56- if ( ! Marshal_IUnknown ( ptr ) )
46+ // Validate IUnknown AddRef/Release usage
47+ int plusOne = Marshal . AddRef ( ptr ) ;
48+ int count = Marshal . Release ( ptr ) ;
49+ if ( ( plusOne - 1 ) != count )
5750 {
58- throw new Exception ( "Failure on native side. Ref counts do not work as expected" ) ;
51+ throw new Exception ( "Ref counts do not work as expected" ) ;
5952 }
60- }
61- finally
62- {
63- if ( ptr != IntPtr . Zero )
64- Marshal . Release ( ptr ) ;
65- }
66- }
67- }
6853
69- public void GetComInterfaceForObjectTest ( )
70- {
71-
72- //test null
73- IntPtr nullPtr = Marshal . GetComInterfaceForObject ( null , typeof ( object ) ) ;
74- if ( nullPtr != IntPtr . Zero )
75- throw new Exception ( "A valid ptr was returned for null object." ) ;
76-
77- foreach ( object obj in TestObjects )
78- {
79- IntPtr ptr = IntPtr . Zero ;
80-
81- try
82- {
83- ptr = Marshal . GetComInterfaceForObject ( obj , typeof ( object ) ) ;
84-
85- if ( ! Marshal_IUnknown ( ptr ) )
54+ // Validate IUnknown QueryInterface usage
55+ Guid noIID = new ( "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" ) ;
56+ int hr = Marshal . QueryInterface ( ptr , noIID , out IntPtr _ ) ;
57+ if ( hr == 0 )
8658 {
87- throw new Exception ( "Failure on native side. Ref counts do not work as expected" ) ;
59+ throw new Exception ( "QueryInterface() does not work as expected" ) ;
8860 }
8961 }
9062 finally
9163 {
9264 if ( ptr != IntPtr . Zero )
93- Marshal . Release ( ptr ) ;
94- }
95- }
96- }
97-
98- public void GetComInterfaceForObjectQueryInterfaceTest ( )
99- {
100- IntPtr nullPtr = Marshal . GetComInterfaceForObject ( null , typeof ( object ) , CustomQueryInterfaceMode . Allow ) ;
101- if ( nullPtr != IntPtr . Zero )
102- throw new Exception ( "A valid ptr was returned for null object." ) ;
103-
104- foreach ( object obj in TestObjects )
105- {
106- IntPtr ptr = IntPtr . Zero ;
107- ptr = Marshal . GetComInterfaceForObject ( obj , typeof ( object ) , CustomQueryInterfaceMode . Allow ) ;
108- try
109- {
110- if ( ! Marshal_IUnknown ( ptr ) )
11165 {
112- throw new Exception ( "Failure on native side. Ref counts do not work as expected" ) ;
113- }
114- }
115- finally
116- {
117- if ( ptr != IntPtr . Zero )
11866 Marshal . Release ( ptr ) ;
67+ }
11968 }
12069 }
12170 }
12271
12372 public void GetObjectForIUnknownTest ( )
12473 {
125- try
126- {
127- //test IntPtr.Zero
128- Object nullObj = Marshal . GetObjectForIUnknown ( IntPtr . Zero ) ;
129-
130- }
131- catch ( ArgumentNullException ) { }
74+ // Test null
75+ Assert . Throws < ArgumentNullException > ( ( ) => Marshal . GetObjectForIUnknown ( IntPtr . Zero ) ) ;
13276
13377 foreach ( object obj in TestObjects )
13478 {
@@ -138,69 +82,31 @@ public void GetObjectForIUnknownTest()
13882 {
13983 ptr = Marshal . GetIUnknownForObject ( obj ) ;
14084
141- Object tmpObj = Marshal . GetObjectForIUnknown ( ptr ) ;
85+ var tmpObj = Marshal . GetObjectForIUnknown ( ptr ) ;
14286
14387 //compare the new object reference with the original object, they should point to the same underlying object
14488 if ( ! object . ReferenceEquals ( obj , tmpObj ) )
89+ {
14590 throw new Exception ( "GetObjectForIUnknown returned a different object. Original: " + obj + ", New: " + tmpObj ) ;
91+ }
14692 }
14793 finally
14894 {
14995 if ( ptr != IntPtr . Zero )
96+ {
15097 Marshal . Release ( ptr ) ;
98+ }
15199 }
152100 }
153101 }
154102
155- public void GetUniqueObjectForIUnknownTest ( )
156- {
157-
158- //test IntPtr.Zero
159- Object nullObj = Marshal . GetUniqueObjectForIUnknown ( IntPtr . Zero ) ;
160-
161- if ( nullObj != null )
162- throw new Exception ( "Object returned for IntPtr.Zero is not null." ) ;
163-
164-
165- foreach ( object obj in TestObjects )
166- {
167- IntPtr ptr = IntPtr . Zero ;
168- object tmpObj = null ;
169-
170- try
171- {
172- ptr = Marshal . GetIUnknownForObject ( obj ) ;
173-
174- tmpObj = Marshal . GetUniqueObjectForIUnknown ( ptr ) ;
175-
176- //compare the new object reference with the original object, they should point to differnet objects
177- if ( object . ReferenceEquals ( obj , tmpObj ) )
178- throw new Exception ( "GetUniqueObjectForIUnknown returned the original object" ) ;
179-
180- //The value should be the same
181- if ( ! obj . Equals ( tmpObj ) )
182- throw new Exception ( "GetUniqueObjectForIUnknown returned an object with different value. Original: " + obj + ", New: " + tmpObj ) ;
183-
184- }
185- finally
186- {
187- if ( tmpObj != null )
188- Marshal . ReleaseComObject ( tmpObj ) ;
189- if ( ptr != IntPtr . Zero )
190- Marshal . Release ( ptr ) ;
191- }
192- }
193- }
194-
195- public bool RunTests ( )
103+ public void RunTests ( )
196104 {
197- Initialize ( ) ;
198105 GetIUnknownForObjectTest ( ) ;
199106 GetObjectForIUnknownTest ( ) ;
200- return true ;
201107 }
202108
203- public bool Initialize ( )
109+ public void Initialize ( )
204110 {
205111 TestObjects = new object [ 7 ] ;
206112 TestObjects [ 0 ] = 1 ; //int
@@ -210,12 +116,10 @@ public bool Initialize()
210116 TestObjects [ 4 ] = new TestClass ( ) ; //Object of type TestClass
211117 TestObjects [ 5 ] = new List < int > ( ) ; //Projected Type
212118 TestObjects [ 6 ] = new Nullable < int > ( 2 ) ; //Nullable Type
213- return true ;
214119 }
215120
216121 [ ConditionalFact ( typeof ( TestLibrary . PlatformDetection ) , nameof ( TestLibrary . PlatformDetection . IsBuiltInComEnabled ) ) ]
217122 [ SkipOnMono ( "Requires COM support" ) ]
218- [ ActiveIssue ( "https://github.com/dotnet/runtime/issues/85234" , typeof ( TestLibrary . Utilities ) , nameof ( TestLibrary . Utilities . IsGCStress ) ) ]
219123 public static void Run ( )
220124 {
221125 IUnknownMarshalingTest testObj = new IUnknownMarshalingTest ( ) ;
@@ -225,7 +129,6 @@ public static void Run()
225129
226130 [ ConditionalFact ( typeof ( TestLibrary . PlatformDetection ) , nameof ( TestLibrary . PlatformDetection . IsBuiltInComEnabled ) ) ]
227131 [ SkipOnMono ( "Requires COM support" ) ]
228- [ ActiveIssue ( "https://github.com/dotnet/runtime/issues/85234" , typeof ( TestLibrary . Utilities ) , nameof ( TestLibrary . Utilities . IsGCStress ) ) ]
229132 public static void RunInALC ( )
230133 {
231134 TestLibrary . Utilities . ExecuteAndUnload ( typeof ( IUnknownMarshalingTest ) . Assembly . Location , nameof ( IUnknownMarshalingTest ) , nameof ( Run ) ) ;
0 commit comments