Skip to content

Commit a1bbba5

Browse files
Add testing for native IDispatch custom marshaller scenario. (#123961)
Addressed test hole discovered in #123832.
1 parent c404e28 commit a1bbba5

File tree

5 files changed

+117
-3
lines changed

5 files changed

+117
-3
lines changed

src/tests/Interop/COM/NETServer/DispatchTesting.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,17 @@ public System.Collections.IEnumerator GetEnumerator()
8989
{
9090
return Enumerable.Range(0, 10).ToList().GetEnumerator();
9191
}
92+
93+
public object TriggerCustomMarshaler(object objIn, ref object objRef)
94+
{
95+
if (!Marshal.IsComObject(objIn))
96+
throw new ArgumentException("objIn is not a COM object");
97+
98+
if (!Marshal.IsComObject(objRef))
99+
throw new ArgumentException("objRef is not a COM object");
100+
101+
var ret = objRef;
102+
objRef = objIn;
103+
return ret;
104+
}
92105
}

src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ void Validate_Double_In_ReturnAndUpdateByRef();
1212
void Validate_LCID_Marshaled();
1313
void Validate_Enumerator();
1414
void Validate_ParamCoerce();
15+
void Validate_TriggerCustomMarshaler();
1516

1617
template<COINIT TM>
1718
struct ComInit
@@ -50,6 +51,7 @@ int __cdecl main()
5051
Validate_LCID_Marshaled();
5152
Validate_Enumerator();
5253
Validate_ParamCoerce();
54+
Validate_TriggerCustomMarshaler();
5355
}
5456
catch (HRESULT hr)
5557
{
@@ -462,6 +464,76 @@ void Validate_Enumerator()
462464
ValidateReturnedEnumerator(&result);
463465
}
464466

467+
struct DummyObject final : public UnknownImpl, public IUnknown
468+
{
469+
STDMETHOD(QueryInterface)(
470+
/* [in] */ REFIID riid,
471+
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
472+
{
473+
return DoQueryInterface(riid, ppvObject, static_cast<IUnknown*>(this));
474+
}
475+
476+
DEFINE_REF_COUNTING();
477+
};
478+
479+
void Validate_TriggerCustomMarshaler()
480+
{
481+
HRESULT hr;
482+
483+
CoreShimComActivation csact{ W("NETServer"), W("DispatchTesting") };
484+
485+
ComSmartPtr<IDispatchTesting> dispatchTesting;
486+
THROW_IF_FAILED(::CoCreateInstance(CLSID_DispatchTesting, nullptr, CLSCTX_INPROC, IID_IDispatchTesting, (void**)&dispatchTesting));
487+
488+
LPOLESTR numericMethodName = (LPOLESTR)W("TriggerCustomMarshaler");
489+
LCID lcid = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT);
490+
DISPID methodId;
491+
492+
::wprintf(W("Invoke %s\n"), numericMethodName);
493+
THROW_IF_FAILED(dispatchTesting->GetIDsOfNames(
494+
IID_NULL,
495+
&numericMethodName,
496+
1,
497+
lcid,
498+
&methodId));
499+
500+
DISPPARAMS params{};
501+
VARIANTARG args[2] = {};
502+
params.cArgs = ARRAY_SIZE(args);
503+
params.rgvarg = args;
504+
505+
ComSmartPtr<IUnknown> objIn;
506+
objIn.Attach(new DummyObject());
507+
ComSmartPtr<IUnknown> objRef;
508+
objRef.Attach(new DummyObject());
509+
510+
ComSmartPtr<IUnknown> pObjRef{ objRef.p };
511+
512+
// IDispatch::Invoke expects arguments in reverse order
513+
V_VT(&args[0]) = VT_UNKNOWN | VT_BYREF;
514+
V_UNKNOWNREF(&args[0]) = &pObjRef;
515+
V_VT(&args[1]) = VT_UNKNOWN;
516+
V_UNKNOWN(&args[1]) = objIn;
517+
518+
VARIANT result{};
519+
THROW_IF_FAILED(dispatchTesting->Invoke(
520+
methodId,
521+
IID_NULL,
522+
lcid,
523+
DISPATCH_METHOD,
524+
&params,
525+
&result,
526+
nullptr,
527+
nullptr
528+
));
529+
530+
THROW_FAIL_IF_FALSE(V_VT(&result) == VT_UNKNOWN);
531+
THROW_FAIL_IF_FALSE(V_UNKNOWN(&result) == objRef);
532+
THROW_FAIL_IF_FALSE(pObjRef == objIn);
533+
534+
::VariantClear(&result);
535+
}
536+
465537
void Validate_ParamCoerce_Success(ComSmartPtr<IDispatchCoerceTesting>& dispatchCoerceTesting, int lcid, DISPID methodId, VARIANT arg, int expected)
466538
{
467539
HRESULT hr;
@@ -538,19 +610,19 @@ void Validate_ParamCoerce()
538610
1,
539611
lcid,
540612
&methodId));
541-
613+
542614
VARIANT arg;
543615

544616
::wprintf(W("Validating VT_UI4\n"));
545617
V_VT(&arg) = VT_UI4;
546618
V_UI4(&arg) = 0x1234ABCD;
547619
Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 0x1234ABCD);
548-
620+
549621
::wprintf(W("Validating VT_I2\n"));
550622
V_VT(&arg) = VT_I2;
551623
V_I2(&arg) = 123;
552624
Validate_ParamCoerce_Success(dispatchCoerceTesting, lcid, methodId, arg, 123);
553-
625+
554626
::wprintf(W("Validating VT_I8\n"));
555627
V_VT(&arg) = VT_I8;
556628
V_I8(&arg) = int64_t(1) << 32;

src/tests/Interop/COM/NativeServer/DispatchTesting.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ class DispatchTesting : public UnknownImpl, public IDispatchTesting
250250
return S_FALSE; // Return a success case to indicate failure to trigger a failure.
251251
}
252252
}
253+
virtual HRESULT STDMETHODCALLTYPE TriggerCustomMarshaler(
254+
/*[in]*/ IUnknown* objIn,
255+
/*[in,out]*/ IUnknown** objRef,
256+
/*[out,retval]*/ IUnknown* pRetVal)
257+
{
258+
return E_NOTIMPL;
259+
}
253260
virtual HRESULT STDMETHODCALLTYPE DoubleHVAValues (
254261
/*[in,out]*/ HFA_4 *input,
255262
/*[out,retval]*/ HFA_4 *pRetVal)

src/tests/Interop/COM/ServerContracts/Server.Contracts.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,21 @@ public struct HRESULT
257257
public int Value;
258258
}
259259

260+
public sealed class CustomObjectMarshaler : ICustomMarshaler
261+
{
262+
public static ICustomMarshaler GetInstance(string cookie) => new CustomObjectMarshaler();
263+
264+
public void CleanUpManagedData(object ManagedObj) => Marshal.ReleaseComObject(ManagedObj);
265+
266+
public void CleanUpNativeData(IntPtr pNativeData) => Marshal.Release(pNativeData);
267+
268+
public int GetNativeDataSize() => IntPtr.Size;
269+
270+
public IntPtr MarshalManagedToNative(object ManagedObj) => Marshal.GetIUnknownForObject(ManagedObj);
271+
272+
public object MarshalNativeToManaged(IntPtr pNativeData) => Marshal.GetObjectForIUnknown(pNativeData);
273+
}
274+
260275
[ComVisible(true)]
261276
[Guid("a5e04c1c-474e-46d2-bbc0-769d04e12b54")]
262277
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
@@ -282,6 +297,9 @@ void DoubleNumeric_ReturnByRef (
282297
double Add_Double_ReturnAndUpdateByRef(double a, ref double b);
283298
void TriggerException(IDispatchTesting_Exception excep, int errorCode);
284299

300+
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(CustomObjectMarshaler))]
301+
object TriggerCustomMarshaler([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(CustomObjectMarshaler))] object objIn, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(CustomObjectMarshaler))] ref object objRef);
302+
285303
// Special cases
286304
HFA_4 DoubleHVAValues(ref HFA_4 input);
287305

src/tests/Interop/COM/ServerContracts/Server.Contracts.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,10 @@ IDispatchTesting : IDispatch
443443
virtual HRESULT STDMETHODCALLTYPE TriggerException (
444444
/*[in]*/ enum IDispatchTesting_Exception excep,
445445
/*[in]*/ int errorCode) = 0;
446+
virtual HRESULT STDMETHODCALLTYPE TriggerCustomMarshaler(
447+
/*[in]*/ IUnknown* objIn,
448+
/*[in,out]*/ IUnknown** objRef,
449+
/*[out,retval]*/ IUnknown* pRetVal) = 0;
446450

447451
// Special cases
448452
virtual HRESULT STDMETHODCALLTYPE DoubleHVAValues(

0 commit comments

Comments
 (0)