| File: Windows\Win32\System\Com\IUnknown.CCW.cs | Web Access |
| Project: src\winforms\src\System.Private.Windows.Core\src\System.Private.Windows.Core.csproj (System.Private.Windows.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Windows.Win32.System.Com; internal unsafe partial struct IUnknown { /// <summary> /// Manual COM Callable Wrapper for <see cref="IUnknown"/>. /// </summary> /// <remarks> /// <para> /// This is for test and debug scenarios only. It should not be used directly in the product. /// </para> /// </remarks> /// <devdoc> /// This is a simplified version of what <see cref="ComWrappers"/> does. It is useful when we want to manage /// our own <see cref="IUnknown.QueryInterface(Guid*, void**)"/> handling for debugging and testing purposes. /// </devdoc> internal static class CCW { private static readonly Vtbl* s_vtable = AllocateVTable(); private static unsafe Vtbl* AllocateVTable() { // Allocate and create a singular VTable for this type projection. Vtbl* vtable = (Vtbl*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(CCW), sizeof(Vtbl)); // IUnknown vtable->QueryInterface_1 = &QueryInterface; vtable->AddRef_2 = &AddRef; vtable->Release_3 = &Release; return vtable; } /// <inheritdoc cref="CCW"/> /// <summary> /// Creates a manual COM Callable Wrapper for the given <paramref name="object"/>. /// </summary> public static unsafe IUnknown* Create(Interface @object) => (IUnknown*)Lifetime<Vtbl, Interface>.Allocate(@object, s_vtable); [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] private static unsafe HRESULT QueryInterface(IUnknown* @this, Guid* iid, void* ppObject) { if (iid is null || ppObject is null) { return HRESULT.E_POINTER; } if (iid->Equals(IID_Guid)) { ppObject = @this; } else { ppObject = null; return HRESULT.E_NOINTERFACE; } Lifetime<Vtbl, Interface>.AddRef(@this); return HRESULT.S_OK; } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] private static unsafe uint AddRef(IUnknown* @this) => Lifetime<Vtbl, Interface>.AddRef(@this); [UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])] private static unsafe uint Release(IUnknown* @this) => Lifetime<Vtbl, Interface>.Release(@this); } }