WineHQ

Wine Developer's Guide/WinRT in Wine: Difference between revisions

(Initial page for WinRT development.)
 
No edit summary
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
__NUMBEREDHEADINGS__
'''Authors:''' Bernhard Koelbl
{{wip}}
== Introduction ==
== Introduction ==


Line 6: Line 9:


Internally, WinRT is basically [[Wine Developer's Guide/COM in Wine|COM]] with extra spice and some "new" concepts.
Internally, WinRT is basically [[Wine Developer's Guide/COM in Wine|COM]] with extra spice and some "new" concepts.
== Writing WinRT components for Wine ==


=== IDL 3.0 ===
=== IDL 3.0 ===


WinRT defines its ABI in IDL files, much like COM. For this, it uses the IDL format 3.0, that has some new concepts, keywords and generally an even more object-oriented approach than the COM-IDLs:
WinRT defines its ABI in IDL files, much like COM. For this, it uses the IDL format 3.0, that has some new concepts, keywords and generally an even more object-oriented approach than the COM-IDLs.


==== Structure ====
==== Structure ====


First, we have the introduction of "runtimeclasses" (this article just refers to them as classes), which are basically COM-objects and the key feature of WinRT:
A WinRT IDL file from the Windows platform SDK is generally structured like this:
Based on their definition and attributes, they expose different COM-interfaces as members or statically. Classes can be instantiated directly [and/or only] through an activation factory (COM class factory), when they are marked by an "activatable" attribute:


<pre>
<pre>
[
import "other.idl"
    activatable(Windows.Foundation.UniversalApiContract, 1.0),
import "other2.idl"
    activatable(Wine.SomeFeature.IFooFactory, Windows.Foundation.UniversalApiContract, 1.0),
 
    contract(Windows.Foundation.UniversalApiContract, 1.0),
// Forward declares of enums, interfaces, structs and runtimeclasses from other files.
    marshaling_behavior(agile),
namespace Windows
    static(Wine.SomeFeature.IFooStatics, Windows.Foundation.UniversalApiContract, 1.0),
    static(Wine.SomeFeature.IFooStatics2, Windows.Foundation.UniversalApiContract, 5.0)
]
runtimeclass Foo
{
{
     [default] interface Windows.SomeFeature.IFoo;
     namespace OtherFeature
     interface Windows.SomeFeature.IFoo2;
    {
        typedef enum OtherFooEnum;
 
        interface OtherFoo;
     }
}
}
</pre>


This Foo class is in the "Wine.SomeFeature" namespace and exposes two interfaces: "IFoo" and "IFoo2":
// Forward declares of enums, interfaces, structs and runtimeclasses in this file.
namespace Windows
{
    namespace SomeFeature  
    {
        interface IFoo;
        interface IFooStatics;
        interface IFooStatics2;


It can be activated (instantiated) either directly (much like a parameterless constructor in any OOP language) or through the "IFooFactory" iface, which provides all (parameterized and non parm.) constructors.
        runtimeclass Bar;
It also exposes static functions, through the interfaces "IFooStatics" and "IFooStatics2".
        runtimeclass BarResult;
        runtimeclass BazHappeningEventArgs;
        runtimeclass Foo;
    }
}


Let's take a look at "IFoo":
// Declaration block of generic interfaces with a type.
namespace Windows
{
    namespace SomeFeature
    {
        declare
        {
            interface Windows.Foundation.IAsyncOperation<Windows.SomeFeature.BarResult*>;
            interface Windows.Foundation.TypedEventHandler<Wine.SomeFeature.Foo*, Wine.SomeFeature.BazHappeningEventArgs*>;
        }
    }
}


<pre>
namespace Windows
[
    contract(Windows.Foundation.UniversalApiContract, 1.0),
    exclusiveto(Wine.SomeFeature.Foo),
    uuid(abababab-cdcd-efef-1234-56789abcdef)
]
interface IFoo : IInspectable
    requires
        Windows.SomeFeature.IFoo2
{
{
     [propget] HRESULT MyProperty1([out, retval] Wine.SomeFeature.Bar **value);
     namespace SomeFeature
    [propput] HRESULT MyProperty1(Wine.SomeFeature.Bar *value);
    {
    HRESULT DoFoobarAsync([out, retval] Windows.Foundation.IAsyncOperation<Wine.SomeFeature.BarResult*> **operation);
        // Definitions of enums, interfaces, structs and runtimeclasses from this file. For more on this, refer to the next section.
    [eventadd] HRESULT OnBazHappening(
 
        [in] Windows.Foundation.TypedEventHandler<Wine.SomeFeature.Foo*, Wine.SomeFeature.BazHappeningEventArgs*> *handler,
        [
        [out, retval] EventRegistrationToken *token);
            contract(Windows.Foundation.UniversalApiContract, 1.0),
    [eventremove] HRESULT OnBazHappening([in] EventRegistrationToken token);
            exclusiveto(Windows.SomeFeature.Foo),
            uuid(abababab-cdcd-efef-1234-56789abcdef)
        ]
        interface IFoo : IInspectable
            requires
                Windows.SomeFeature.IFoo2
        {
            [propget] HRESULT MyProperty1([out, retval] Windows.SomeFeature.Bar **value);
            [propput] HRESULT MyProperty1(Windows.SomeFeature.Bar *value);
            HRESULT CreateOtherFoo([out, retval] Windows.OtherFeature.OtherFoo **other_foo_obj);
            HRESULT DoFoobarAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.SomeFeature.BarResult*> **operation);
            [eventadd] HRESULT OnBazHappening(
                [in] Windows.Foundation.TypedEventHandler<Windows.SomeFeature.Foo*, Windows.SomeFeature.BazHappeningEventArgs*> *handler,
                [out, retval] EventRegistrationToken *token);
            [eventremove] HRESULT OnBazHappening([in] EventRegistrationToken token);
        }
 
        [
            activatable(Windows.Foundation.UniversalApiContract, 1.0),
            activatable(Windows.SomeFeature.IFooFactory, Windows.Foundation.UniversalApiContract, 1.0),
            contract(Windows.Foundation.UniversalApiContract, 1.0),
            marshaling_behavior(agile),
            static(Windows.SomeFeature.IFooStatics, Windows.Foundation.UniversalApiContract, 1.0),
            static(Windows.SomeFeature.IFooStatics2, Windows.Foundation.UniversalApiContract, 5.0)
        ]
        runtimeclass Foo
        {
            [default] interface Windows.SomeFeature.IFoo;
            interface Windows.SomeFeature.IFoo2;
        }
    }
}
}
</pre>
</pre>


*Like any COM-interface, IFoo has an interface-ID (UUID) and it's only meant to be used by the Foo class (exclusiveto).
(Note: I didn't work out this example into far detail, meaning some things may look incomplete.)
 
==== Runtimeclasses ====
 
Now, let's take a look at the definition part from above, in particular the "Foo" "runtimeclass". Runtime classes (I'll refer to them as just classes from now on), are basically COM-objects and the key feature of WinRT:
Based on their definition and attributes, they expose different COM-interfaces as members or statically. Classes can be instantiated directly [and/or only] through an activation factory (COM class factory), when they are marked by an "activatable" attribute.
 
Let's take a look at our example from above in more detail:
*Foo resides in the "Wine.SomeFeature" namespace and has two interface members: "IFoo" and "IFoo2"
*It can be activated (instantiated) either directly (much like a parameterless constructor in any OOP language) or through the "IFooFactory" iface, which provides all (parameterized and non parm.) constructors.
*It also exposes static functions, through the interfaces "IFooStatics" and "IFooStatics2".
 
==== Interfaces ====
 
Interfaces in WinRT are mostly the same as in COM, but they have some additional features.
 
Let's take a closer look at "IFoo":
*Like any COM-interface, IFoo has an interface-ID (UUID)
*It's only meant to be used by the Foo class, thus marked with the "exclusiveto" property.
*It inherits from IInspectable, which in turn also inherits IUnknown.
*It inherits from IInspectable, which in turn also inherits IUnknown.
*Any class that implements the IFoo interface also needs to implement the IFoo2 interface, denoted by "requires".
*Any class that implements the IFoo interface also needs to implement the IFoo2 interface, denoted by "requires".
 
*The interface's contents:
 
Let's take a look at the interface members:
# IFoo has a property with getter and setter for a Bar object: "MyProperty1".
# IFoo has a property with getter and setter for a Bar object: "MyProperty1".
# IFoo has a method, which does its work asynchronously using the parameterized interface "IAsyncOperation".
# IFoo has a method, which does its work asynchronously using the parameterized interface "IAsyncOperation".
# IFoo provides an event system "OnBazHappening".
# IFoo provides an event system "OnBazHappening".


==== Properties ====


Summing up some properties:
You might already have noticed the huge amount of new properties IDL 3.0 brings with.
This paragraph has a brief list of them:


{|class="wikitable"
{|class="wikitable"
Line 78: Line 139:
!Description
!Description
|-
|-
|| activatable || An activatable (runtime)class
|| activatable || An activatable (runtime) class
|-
|-
|| default    || The default interface of an instantiated class
|| default    || The default interface of an instantiated (runtime) class
|-
|-
|| eventadd    || Function to add an event handler
|| eventadd    || Function to add an event handler
|-
|-
|| eventremove || Function to remove an event handler
|| eventremove || Function to remove an event handler
|-
|| out        || A value that is returned from a function, by reference - (Like out in C#)
|-
|-
|| propget    || Getter method of a property
|| propget    || Getter method of a property
|-
|-
|| propput    || Setter method of a property
|| propput    || Setter method of a property
|-
|| retval      || The value that's used as return value in the C++ WinRT API
|-
|-
|| static      || A static interface to a class
|| static      || A static interface to a class
|-
|-
|}
|}
== Writing WinRT components for Wine ==
=== Style ===
WinRT components for Wine should be written in either Julliard style (e.g. ntdll, Windows.Gaming.Input) or WineD3D style (d3d11, vkd3d), with some minor additions:
*In WinRT, lines can get very long due to the wild naming schemes introduced, so the imaginary max length of a line should be set at around 160 characters (instead of 120).
*Replace STDMETHODCALLTYPE with WINAPI to reduce line length.
----
----
[[Category:Development]]
[[Category:Development]]

Latest revision as of 16:37, 29 August 2022

__NUMBEREDHEADINGS__ Authors: Bernhard Koelbl

Work in progress: This page is currently undergoing extensive revision. External links to specific parts of this page may now be broken due to the section having been edited, moved, merged with another section, or removed altogether. Consult the table of contents to find the section you are looking for. There may be related discussion on the talk page.

Introduction

What is WinRT?

Windows Runtime (short: WinRT) is a new Win32 independent ABI, used by the Windows operating system. It finds its primary use in the Universal Windows Platform (UWP), which provides an API and execution environment (sandbox) to run apps in, but can also be directly accessed from Win32 programs.

Internally, WinRT is basically COM with extra spice and some "new" concepts.

IDL 3.0

WinRT defines its ABI in IDL files, much like COM. For this, it uses the IDL format 3.0, that has some new concepts, keywords and generally an even more object-oriented approach than the COM-IDLs.

Structure

A WinRT IDL file from the Windows platform SDK is generally structured like this:

import "other.idl"
import "other2.idl"

// Forward declares of enums, interfaces, structs and runtimeclasses from other files.
namespace Windows
{
    namespace OtherFeature
    {
        typedef enum OtherFooEnum;

        interface OtherFoo;
    }
}

// Forward declares of enums, interfaces, structs and runtimeclasses in this file.
namespace Windows
{
    namespace SomeFeature 
    {
        interface IFoo;
        interface IFooStatics;
        interface IFooStatics2;

        runtimeclass Bar;
        runtimeclass BarResult;
        runtimeclass BazHappeningEventArgs;
        runtimeclass Foo;
    }
}

// Declaration block of generic interfaces with a type.
namespace Windows
{
    namespace SomeFeature
    {
        declare
        {
            interface Windows.Foundation.IAsyncOperation<Windows.SomeFeature.BarResult*>;
            interface Windows.Foundation.TypedEventHandler<Wine.SomeFeature.Foo*, Wine.SomeFeature.BazHappeningEventArgs*>;
        }
    }
}

namespace Windows
{
    namespace SomeFeature
    {
        // Definitions of enums, interfaces, structs and runtimeclasses from this file. For more on this, refer to the next section.

        [
            contract(Windows.Foundation.UniversalApiContract, 1.0),
            exclusiveto(Windows.SomeFeature.Foo),
            uuid(abababab-cdcd-efef-1234-56789abcdef)
        ]
        interface IFoo : IInspectable
            requires
                Windows.SomeFeature.IFoo2
        {
            [propget] HRESULT MyProperty1([out, retval] Windows.SomeFeature.Bar **value);
            [propput] HRESULT MyProperty1(Windows.SomeFeature.Bar *value);
            HRESULT CreateOtherFoo([out, retval] Windows.OtherFeature.OtherFoo **other_foo_obj);
            HRESULT DoFoobarAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.SomeFeature.BarResult*> **operation);
            [eventadd] HRESULT OnBazHappening(
                [in] Windows.Foundation.TypedEventHandler<Windows.SomeFeature.Foo*, Windows.SomeFeature.BazHappeningEventArgs*> *handler,
                [out, retval] EventRegistrationToken *token);
            [eventremove] HRESULT OnBazHappening([in] EventRegistrationToken token);
        }

        [
            activatable(Windows.Foundation.UniversalApiContract, 1.0),
            activatable(Windows.SomeFeature.IFooFactory, Windows.Foundation.UniversalApiContract, 1.0),
            contract(Windows.Foundation.UniversalApiContract, 1.0),
            marshaling_behavior(agile),
            static(Windows.SomeFeature.IFooStatics, Windows.Foundation.UniversalApiContract, 1.0),
            static(Windows.SomeFeature.IFooStatics2, Windows.Foundation.UniversalApiContract, 5.0)
        ]
        runtimeclass Foo
        {
            [default] interface Windows.SomeFeature.IFoo;
            interface Windows.SomeFeature.IFoo2;
        }
    }
}

(Note: I didn't work out this example into far detail, meaning some things may look incomplete.)

Runtimeclasses

Now, let's take a look at the definition part from above, in particular the "Foo" "runtimeclass". Runtime classes (I'll refer to them as just classes from now on), are basically COM-objects and the key feature of WinRT: Based on their definition and attributes, they expose different COM-interfaces as members or statically. Classes can be instantiated directly [and/or only] through an activation factory (COM class factory), when they are marked by an "activatable" attribute.

Let's take a look at our example from above in more detail:

  • Foo resides in the "Wine.SomeFeature" namespace and has two interface members: "IFoo" and "IFoo2"
  • It can be activated (instantiated) either directly (much like a parameterless constructor in any OOP language) or through the "IFooFactory" iface, which provides all (parameterized and non parm.) constructors.
  • It also exposes static functions, through the interfaces "IFooStatics" and "IFooStatics2".

Interfaces

Interfaces in WinRT are mostly the same as in COM, but they have some additional features.

Let's take a closer look at "IFoo":

  • Like any COM-interface, IFoo has an interface-ID (UUID)
  • It's only meant to be used by the Foo class, thus marked with the "exclusiveto" property.
  • It inherits from IInspectable, which in turn also inherits IUnknown.
  • Any class that implements the IFoo interface also needs to implement the IFoo2 interface, denoted by "requires".
  • The interface's contents:
  1. IFoo has a property with getter and setter for a Bar object: "MyProperty1".
  2. IFoo has a method, which does its work asynchronously using the parameterized interface "IAsyncOperation".
  3. IFoo provides an event system "OnBazHappening".

Properties

You might already have noticed the huge amount of new properties IDL 3.0 brings with. This paragraph has a brief list of them:

Property Description
activatable An activatable (runtime) class
default The default interface of an instantiated (runtime) class
eventadd Function to add an event handler
eventremove Function to remove an event handler
out A value that is returned from a function, by reference - (Like out in C#)
propget Getter method of a property
propput Setter method of a property
retval The value that's used as return value in the C++ WinRT API
static A static interface to a class

Writing WinRT components for Wine

Style

WinRT components for Wine should be written in either Julliard style (e.g. ntdll, Windows.Gaming.Input) or WineD3D style (d3d11, vkd3d), with some minor additions:

  • In WinRT, lines can get very long due to the wild naming schemes introduced, so the imaginary max length of a line should be set at around 160 characters (instead of 120).
  • Replace STDMETHODCALLTYPE with WINAPI to reduce line length.



This page was last edited on 29 August 2022, at 16:37.