import CWinRT internal let IID_IMarshal: IID = IID(Data1: 0x01000300, Data2: 0x0000, Data3: 0x0000, Data4: (0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)) // 01000300-0000-0000-C000-00000046 fileprivate extension IUnknownRef { func copyTo(_ riid: REFIID?, _ ppvObj: UnsafeMutablePointer?) -> HRESULT { self.borrow.pointee.lpVtbl.pointee.QueryInterface(self.borrow, riid, ppvObj) } } func makeMarshaler(_ outer: IUnknownRef, _ result: UnsafeMutablePointer) throws { let marshaler = try Marshaler(outer) let wrapper = MarshalWrapper(marshaler) try wrapper.toABI { _ = $0.pointee.lpVtbl.pointee.AddRef($0) result.pointee = UnsafeMutableRawPointer($0) } } fileprivate class MarshalWrapper: WinRTAbiBridgeWrapper { init(_ marshaler: Marshaler){ super.init(IMarshalBridge.makeAbi(), marshaler) } } fileprivate enum IMarshalBridge: AbiBridge { static func makeAbi() -> C_IMarshal { return C_IMarshal(lpVtbl: &IMarshalVTable) } static func from(abi: ComPtr?) -> Marshaler? { guard let abi = abi else { return nil } return try? Marshaler(IUnknownRef(abi)) } typealias CABI = C_IMarshal typealias SwiftProjection = Marshaler } private var IMarshalVTable: C_IMarshalVtbl = .init( QueryInterface: { pUnk, riid, ppvObject in guard let pUnk, let riid, let ppvObject else { return E_INVALIDARG } switch riid.pointee { case IID_IMarshal: _ = pUnk.pointee.lpVtbl.pointee.AddRef(pUnk) return S_OK default: guard let obj = MarshalWrapper.tryUnwrapFromBase(raw: pUnk)?.obj else { return E_NOINTERFACE } return obj.copyTo(riid, ppvObject) } }, AddRef: { MarshalWrapper.addRef($0) }, Release: { MarshalWrapper.release($0) }, GetUnmarshalClass: { Marshaler.GetUnmarshalClass($0, $1, $2, $3, $4, $5, $6) }, GetMarshalSizeMax: { Marshaler.GetMarshalSizeMax($0, $1, $2, $3, $4, $5, $6) }, MarshalInterface: { Marshaler.MarshalInterface($0, $1, $2, $3, $4, $5, $6) }, UnmarshalInterface: { Marshaler.UnmarshalInterface($0, $1, $2, $3)}, ReleaseMarshalData: { Marshaler.ReleaseMarshalData($0, $1) }, DisconnectObject: { Marshaler.DisconnectObject($0, $1) } ) private class Marshaler { var obj: IUnknownRef init(_ obj: IUnknownRef) throws { self.obj = obj var marshalerPtr: UnsafeMutablePointer? try CHECKED(CoCreateFreeThreadedMarshaler(nil, &marshalerPtr)) guard let marshalerPtr else { throw WindowsFoundation.Error(hr: E_FAIL) } marshaler = UnsafeMutableRawPointer(marshalerPtr).bindMemory(to: C_IMarshal.self, capacity: 1) } deinit { _ = marshaler.pointee.lpVtbl.pointee.Release(marshaler) } var marshaler: UnsafeMutablePointer static func GetUnmarshalClass( _ this: UnsafeMutablePointer?, _ riid: REFIID?, _ pv: UnsafeMutableRawPointer?, _ dwDestContext: DWORD, _ pvDestContext: UnsafeMutableRawPointer?, _ mshlflags: DWORD, _ pCid: UnsafeMutablePointer?) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.GetUnmarshalClass(marshaler, riid, pv, dwDestContext, pvDestContext, mshlflags, pCid) } static func GetMarshalSizeMax( _ this: UnsafeMutablePointer?, _ riid: REFIID?, _ pv: UnsafeMutableRawPointer?, _ dwDestContext: DWORD, _ pvDestContext: UnsafeMutableRawPointer?, _ mshlflags: DWORD, _ pSize: UnsafeMutablePointer?) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.GetMarshalSizeMax(marshaler, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize) } static func MarshalInterface( _ this: UnsafeMutablePointer?, _ pStm: UnsafeMutablePointer?, _ riid: REFIID?, _ pv: UnsafeMutableRawPointer?, _ dwDestContext: DWORD, _ pvDestContext: UnsafeMutableRawPointer?, _ mshlflags: DWORD) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.MarshalInterface(marshaler, pStm, riid, pv, dwDestContext, pvDestContext, mshlflags) } static func UnmarshalInterface( _ this: UnsafeMutablePointer?, _ pStm: UnsafeMutablePointer?, _ riid: REFIID?, _ ppv: UnsafeMutablePointer?) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.UnmarshalInterface(marshaler, pStm, riid, ppv) } static func ReleaseMarshalData( _ this: UnsafeMutablePointer?, _ pStm: UnsafeMutablePointer?) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.ReleaseMarshalData(marshaler, pStm) } static func DisconnectObject( _ this: UnsafeMutablePointer?, _ dwReserved: DWORD) -> HRESULT { guard let marshaler = MarshalWrapper.tryUnwrapFrom(abi: ComPtr(this))?.marshaler else { return E_FAIL } return marshaler.pointee.lpVtbl.pointee.DisconnectObject(marshaler, dwReserved) } }