diff --git a/Support/Sources/COM/COMExport.swift b/Support/Sources/COM/COMExport.swift index 89b83cb6..f5d7f407 100644 --- a/Support/Sources/COM/COMExport.swift +++ b/Support/Sources/COM/COMExport.swift @@ -24,10 +24,10 @@ open class COMExportBase: IUnknownProtocol { open class var implements: [Implements] { [] } fileprivate var comInterface: COMExportedInterface - public var unknownPointer: IUnknownPointer { comInterface.pointer } + public var unknownPointer: IUnknownPointer { comInterface.unknownPointer } open var anyImplementation: Any { self } - fileprivate init(later: Void) { comInterface = .null } + fileprivate init(later: Void) { comInterface = .uninitialized } open func _queryInterfacePointer(_ id: COMInterfaceID) throws -> IUnknownPointer { if id == IUnknownProjection.id { return unknownPointer.addingRef() } @@ -52,12 +52,12 @@ open class COMExportBase: IUnknownProtocol { } public static func getImplementationUnsafe(_ this: Projection.COMPointer, projection: Projection.Type) -> Projection.SwiftObject { - getImplementation(unwrapped: COMExportedInterface.unwrapObjectUnsafe(IUnknownPointer.cast(this)), projection: Projection.self)! + getImplementation(unwrapped: COMExportedInterface.unwrapUnsafe(this), projection: Projection.self)! } public static func getImplementation(_ this: Projection.COMPointer, projection: Projection.Type) -> Projection.SwiftObject? { - guard COMExportedInterface.test(IUnknownPointer.cast(this)) else { return nil } - return getImplementation(unwrapped: COMExportedInterface.unwrapObjectUnsafe(IUnknownPointer.cast(this)), projection: Projection.self) + guard COMExportedInterface.test(this) else { return nil } + return getImplementation(unwrapped: COMExportedInterface.unwrapUnsafe(this), projection: Projection.self) } } @@ -65,15 +65,12 @@ open class COMExportBase: IUnknownProtocol { open class COMExport: COMExportBase { open var implementation: Projection.SwiftObject { self as! Projection.SwiftObject } public var comPointer: Projection.COMPointer { - comInterface.pointer.withMemoryRebound(to: Projection.COMInterface.self, capacity: 1) { $0 } + comInterface.unknownPointer.cast(to: Projection.COMInterface.self) } public init() { super.init(later: ()) - comInterface = .init( - swiftObject: self, - virtualTable: Projection.virtualTablePointer.withMemoryRebound( - to: IUnknownProjection.COMVirtualTable.self, capacity: 1) { $0 }) + comInterface = .init(swiftObject: self, virtualTable: Projection.virtualTablePointer) } open override func _queryInterfacePointer(_ id: COMInterfaceID) throws -> IUnknownPointer { diff --git a/Support/Sources/COM/COMExportedInterface.swift b/Support/Sources/COM/COMExportedInterface.swift index 138c0ef8..b8184d43 100644 --- a/Support/Sources/COM/COMExportedInterface.swift +++ b/Support/Sources/COM/COMExportedInterface.swift @@ -3,7 +3,7 @@ import CWinRTCore /// Lays out a COM interface for exporting to COM consumers. public struct COMExportedInterface { private static let markerInterfaceId: COMInterfaceID = .init(0x33934271, 0x7009, 0x4EF3, 0x90F1, 0x02090D7EBD64) - public static var null: COMExportedInterface { .init() } + public static var uninitialized: COMExportedInterface { .init() } private var comObject: CWinRTCore.SWRT_SwiftCOMObject @@ -11,13 +11,17 @@ public struct COMExportedInterface { comObject = .init() } - public init(swiftObject: SwiftObject, virtualTable: IUnknownProjection.COMVirtualTablePointer) { + public init( + swiftObject: SwiftObject, + virtualTable: UnsafePointer) { comObject = .init( - comVirtualTable: virtualTable, + comVirtualTable: virtualTable.withMemoryRebound(to: CWinRTCore.SWRT_IUnknownVTable.self, capacity: 1) { $0 }, swiftObject: Unmanaged.passUnretained(swiftObject).toOpaque()) } - public var pointer: IUnknownPointer { + public var isInitialized: Bool { comObject.swiftObject != nil } + + public var unknownPointer: IUnknownPointer { mutating get { withUnsafeMutablePointer(to: &comObject) { IUnknownPointer.cast($0) @@ -25,30 +29,22 @@ public struct COMExportedInterface { } } - fileprivate static func toUnmanagedUnsafe(_ this: IUnknownPointer) -> Unmanaged { + fileprivate static func toUnmanagedUnsafe(_ this: UnsafeMutablePointer) -> Unmanaged { this.withMemoryRebound(to: CWinRTCore.SWRT_SwiftCOMObject.self, capacity: 1) { Unmanaged.fromOpaque($0.pointee.swiftObject) } } - public static func test(_ this: IUnknownPointer) -> Bool { - do { try this.queryInterface(markerInterfaceId).release() } catch { return false } + public static func test(_ this: UnsafeMutablePointer) -> Bool { + do { try IUnknownPointer.cast(this).queryInterface(markerInterfaceId).release() } catch { return false } return true } - public static func unwrapObjectUnsafe(_ this: IUnknownPointer) -> AnyObject { + public static func unwrapUnsafe(_ this: UnsafeMutablePointer) -> AnyObject { toUnmanagedUnsafe(this).takeUnretainedValue() } - public static func unwrapObject(_ this: IUnknownPointer) -> AnyObject? { - test(this) ? unwrapUnsafe(this) : nil - } - - public static func unwrapUnsafe(_ this: IUnknownPointer) -> IUnknown { - unwrapObjectUnsafe(this) as! IUnknown - } - - public static func unwrap(_ this: IUnknownPointer) -> IUnknown? { + public static func unwrap(_ this: UnsafeMutablePointer) -> AnyObject? { test(this) ? unwrapUnsafe(this) : nil } } @@ -97,7 +93,9 @@ extension COMExportedInterface { return HResult.catchValue { let id = GUIDProjection.toSwift(iid.pointee) let this = IUnknownPointer.cast(this) - let unknownWithRef = id == markerInterfaceId ? this.addingRef() : try unwrapUnsafe(this)._queryInterfacePointer(id) + let unknownWithRef = id == markerInterfaceId + ? this.addingRef() + : try (unwrapUnsafe(this) as! IUnknown)._queryInterfacePointer(id) ppvObject.pointee = UnsafeMutableRawPointer(unknownWithRef) } } diff --git a/Support/Sources/COM/COMInterfaceID.swift b/Support/Sources/COM/COMInterfaceID.swift index cba90a0a..e2181f94 100644 --- a/Support/Sources/COM/COMInterfaceID.swift +++ b/Support/Sources/COM/COMInterfaceID.swift @@ -3,7 +3,7 @@ import struct Foundation.UUID public typealias COMInterfaceID = Foundation.UUID extension COMInterfaceID { - // Initializer supporting a GUID-like syntax: .init(0x00000000, 0x0000, 0x0000, 0xC000, 0x000000000046) + /// Initializer supporting a GUID-like syntax: .init(0x00000000, 0x0000, 0x0000, 0xC000, 0x000000000046) public init(_ data1: UInt32, _ data2: UInt16, _ data3: UInt16, _ data4: UInt16, _ data5: UInt64) { precondition(data5 < 0x1_00_00_00_00_00_00) let bytes = ( @@ -16,4 +16,18 @@ extension COMInterfaceID { UInt8((data5 >> 8) & 0xFF), UInt8((data5 >> 0) & 0xFF)) self.init(uuid: bytes) } + + /// Initializer for copying out of ILSpy + /// [Windows.Foundation.Metadata.Guid(2908547984u, 62745, 22786, 149, 48, 215, 242, 47, 226, 221, 132)] + public init( + _ data1: UInt32, _ data2: UInt16, _ data3: UInt16, + _ data4: UInt8, _ data5: UInt8, _ data6: UInt8, _ data7: UInt8, + _ data8: UInt8, _ data9: UInt8, _ data10: UInt8, _ data11: UInt8) { + let bytes = ( + UInt8((data1 >> 24) & 0xFF), UInt8((data1 >> 16) & 0xFF), UInt8((data1 >> 8) & 0xFF), UInt8((data1 >> 0) & 0xFF), + UInt8((data2 >> 8) & 0xFF), UInt8((data2 >> 0) & 0xFF), + UInt8((data3 >> 8) & 0xFF), UInt8((data3 >> 0) & 0xFF), + data4, data5, data6, data7, data8, data9, data10, data11) + self.init(uuid: bytes) + } } \ No newline at end of file diff --git a/Support/Sources/WindowsRuntime/WinRTExportedInterface.swift b/Support/Sources/WindowsRuntime/WinRTExportedInterface.swift index 5ba42601..90677b63 100644 --- a/Support/Sources/WindowsRuntime/WinRTExportedInterface.swift +++ b/Support/Sources/WindowsRuntime/WinRTExportedInterface.swift @@ -1,60 +1,8 @@ import COM import CWinRTCore -/// Lays out a WinRT interface for exporting to WinRT consumers. -public struct WinRTExportedInterface { - public static var null: WinRTExportedInterface { .init() } - - private var com: COMExportedInterface - - private init() { - com = .null - } - - public init(swiftObject: SwiftObject, virtualTable: IInspectableProjection.COMVirtualTablePointer) { - com = .init( - swiftObject: swiftObject, - virtualTable: virtualTable.withMemoryRebound(to: IUnknownProjection.COMVirtualTable.self, capacity: 1) { $0 }) - } - - public var unknownPointer: IUnknownPointer { - mutating get { - com.pointer - } - } - - public var inspectablePointer: IInspectablePointer { - mutating get { - IInspectablePointer.cast(com.pointer) - } - } - - public static func unwrapUnsafe(_ this: IInspectablePointer) -> IInspectable { - COMExportedInterface.unwrapObjectUnsafe(IUnknownPointer.cast(this)) as! IInspectable - } - - public static func unwrap(_ this: IInspectablePointer) -> IInspectable? { - COMExportedInterface.test(IUnknownPointer.cast(this)) ? unwrapUnsafe(this) : nil - } -} - /// IInspectable virtual table implementations -extension WinRTExportedInterface { - public static func AddRef(_ this: UnsafeMutablePointer?) -> UInt32 { - COMExportedInterface.AddRef(this) - } - - public static func Release(_ this: UnsafeMutablePointer?) -> UInt32 { - COMExportedInterface.Release(this) - } - - public static func QueryInterface( - _ this: UnsafeMutablePointer?, - _ iid: UnsafePointer?, - _ ppvObject: UnsafeMutablePointer?) -> CWinRTCore.SWRT_HResult { - COMExportedInterface.QueryInterface(this, iid, ppvObject) - } - +public enum WinRTExportedInterface { public static func GetIids( _ this: UnsafeMutablePointer?, _ count: UnsafeMutablePointer?, @@ -62,7 +10,7 @@ extension WinRTExportedInterface { guard let this, let count, let iids else { return HResult.invalidArg.value } count.pointee = 0 iids.pointee = nil - let object = unwrapUnsafe(IInspectablePointer.cast(this)) + let object = COMExportedInterface.unwrapUnsafe(this) as! IInspectable return HResult.catchValue { let idsArray = try object.getIids() let comArray = try WinRTArrayProjection.toABI(idsArray) @@ -76,7 +24,7 @@ extension WinRTExportedInterface { _ className: UnsafeMutablePointer?) -> CWinRTCore.SWRT_HResult { guard let this, let className else { return HResult.invalidArg.value } className.pointee = nil - let object = unwrapUnsafe(IInspectablePointer.cast(this)) + let object = COMExportedInterface.unwrapUnsafe(this) as! IInspectable return HResult.catchValue { className.pointee = try HStringProjection.toABI(object.getRuntimeClassName()) } @@ -86,7 +34,7 @@ extension WinRTExportedInterface { _ this: UnsafeMutablePointer?, _ trustLevel: UnsafeMutablePointer?) -> CWinRTCore.SWRT_HResult { guard let this, let trustLevel else { return HResult.invalidArg.value } - let object = unwrapUnsafe(IInspectablePointer.cast(this)) + let object = COMExportedInterface.unwrapUnsafe(this) as! IInspectable return HResult.catchValue { trustLevel.pointee = try TrustLevel.toABI(object.getTrustLevel()) }