itcamp 2013 - raffaele rialdi - windows runtime (winrt) deep dive
TRANSCRIPT
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Windows Runtime (WinRT) deep dive
Raffaele Rialdi
@raffaeler
[email protected] http://www.iamraf.net
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Huge thanks to our sponsors!
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Spot the difference
Using a pure .NET library
Using a Windows Runtime native library projected in .NET
<!DOCTYPE html> <html> <head> <title>IAmRaf - Home Page</title> <meta name="description" content="Raffaele Rialdi home page" /> …
using System.Net.Http;
... using (var client = new HttpClient()) { var res = await client.GetStringAsync( "http://www.iamraf.net"); // ... }
using Windows.Web.Syndication; ... var client = new SyndicationClient(); var feed = await client.RetrieveFeedAsync( new Uri("http://www.iamraf.net/rss")); var firstItem = feed.Items.FirstOrDefault(); var content = firstItem.Summary.Text;
The new Windows start screen 8 shows a number of tiles that may look like a revamped version of the old shortcuts: But appearances can be deceptive and tiles are not shortcuts and they do not launch directly the application process. The crucial point is that Windows Runtime (WinRT) is the laye...
itcampro @ itcamp13 # Premium conference on Microsoft technologies
COMPONENTS UNDER THE HOOD
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Classic C++ polimorphism is static
• Polimorphism is possible only if class definitions are known
– It must be done at compile time because C++ provides no
binary contract
class myBase { public: virtual void Foo() { …} virtual void Bar() { … } };
class myDerived : public myBase { public: void Foo() override { … } void Bar() override { … } };
vTable
myBase::Foo
myBase::Bar
VTable
myDerived::Foo
myDerived::Bar
Patched at compile time!
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Inter-assembly Inheritance (.NET "trick")
Assembly 1
public class mybase { public virtual void Foo() { } public void Bar() { } }
Assembly 2
public class myderived : mybase { public override void Foo() { } public void Qux() { } }
MethodTable
ToString
Equals
GetHashCode
Finalize
Foo
Bar
Qux
MethodTable
ToString
Equals
GetHashCode
Finalize
Foo
Bar
Syst
em.O
bje
ct
Patched at runtime!
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• We need a binary contract
– Metadata to define the Type System
– Runtime to manage the runtime behavior
Solution: metadata and runtime
MethodTable
AddRef
Release
QueryInterface
GetIids
GetRuntimeClassName
GetTrustLevel
Foo
Bar
Qux
IUnknown
IInspectable
IMyBase
IMyDerived
1. Dynamic interface discovery • IUnknown.QueryInterface is the
runtime equivalent of a cast or • IInspectable.GetIids
(javascript only)
2. New rule: cannot derive any
component with the exception of XAML controls • Reason? Versioning!
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Modeling by interface
• Why? Because Modeling by interface is simpler!
• Interfaces are the public surface of the component – Identified by an IID (Guid)
– Can be marked as “exclusiveto” for a specific component
• The class implementing the interface – Identified by the namespace.nome string
– Class is “hidden” and never visible • Can only be riched with the use of interface
• C++ can bypass the interface for perf reasons
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
Code is always accessed by interface!
Projections make interfaces appear like they were classes
The "new" operation is fake
var client = new SyndicationClient();
ComPtr<ISyndicationClient> spClient; auto classId = HStringReference( RuntimeClass_Windows_Web_Syndication_SyndicationClient).Get(); hr = ActivateInstance(classId, &spClient); if(FAILED(hr)) return PrintError(hr);
HRESULT hr; ComPtr<IActivationFactory> spFactory; auto classId = HStringReference( RuntimeClass_Windows_Web_Syndication_SyndicationClient).Get(); hr = GetActivationFactory(classId, &spFactory); if(FAILED(hr)) return PrintError(hr); ComPtr<ISyndicationClient> spSyndicationClient; hr = spActivationFactory->ActivateInstance(&spSyndicationClient); if(FAILED(hr)) return PrintError(hr);
The long way (C++ and WRL Library)
The short way (C++ and WRL Library)
The C++ projection (C++/CX)
auto client = ref new SyndicationClient();
C# projection
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• How can static methods exists if the surface is only exposed by interfaces?
• COM did not support static methods
• WinRT do support them – But static methods cannot be part of an interface!
• Solution: statics are instance methods of the factory – The interface exposing the static methods is
automatically generated by the compiler
• Projections make them appear as if they were part of the class
Static methods
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• QueryInterface
– Discover interfaces in a component
• IUnknown: AddRef e Release
– Managing the lifecycle
• Circular References risk
– WeakReference is the solution
– SDKs/ Projections create the WeakRef for us
Component lifecycle
A B
Root
Parent
Parent
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• Make use of the WinRT metadata to map:
– Base types (int, double, string, …)
– Complex types • INotifyPropertyChanged, collections, ...
• Extension methods for non-mappable types
– Streams, Storage, Async
• Make use of the CCW and RCW as it was in COM
• Native HRESULTS are converted into Exceptions and vice-versa
.NET projection
itcampro @ itcamp13 # Premium conference on Microsoft technologies
DEMO: SPYCOMPONENT
itcampro @ itcamp13 # Premium conference on Microsoft technologies
THE VIEW ARCHITECTURE
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• The main function
– It's always there
• The message pump
– It's there too
• One single thread allowed to interact with
the UI
– Nothing changed here too
• But …
Once upon a time …
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• Once started the App becomes a component
– Like the old COM exe server
• OS and Apps interact via Contracts
– They are interfaces with new high level IPC
• The UI sits on DirectX
– Pure DX with C++
– Mixed XAML and DX with C++
– Pure XAML with C++ and .NET
– HTML with Javascript
Infrastructure differences
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile The view lifecycle
WinRT App IFramework ViewSource
IFramework View
main
CoreApplication.Run
create
CreateView create
Initialize
SetWindow
Load
Run
Uninitialize
User interaction
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• Needed because components cannot always be accessed by any thread
• Apartment is a group of one or more threads who can legally invoke a component
– MTA: total threads freedom and better perf
– STA: one single thread at a time • calls are enqueued to avoid concurrency
– ASTA: new STA which avoid re-entrancy • used for the primary UI thread in Win8 Apps
• Marshaling is minimized because of the new "Agile" concept
Threading model: Apartments
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• Most of the WinRT library is marked as "both"
– compatbile with MTA and (A)STA
• XAML is "both" but at runtime enforce to be called by ASTA only
• Share target Contract are opened in a different ASTA!
– One of the primary sources of bugs in Windows Store Applications
• Be careful to use the correct Dispatcher
Threading and library
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Threading, Async and Dispatcher
• Languages offer async support in different
flavors
– Async/Await (.NET)
– Promise (C++, Js)
• Async use the SynchronizationContext to find
the primary thread where the callback will be
executed
• If you call Dispacher.Invoke by yourself
– Pay attention: every ASTA has a different
Dispatcher
itcampro @ itcamp13 # Premium conference on Microsoft technologies
SECURITY!
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile AppContainer restrictions
• Limitations derived from Low Integrity Level
• API restrictions:
– Limited Win32 API and COM Interfaces
– .NET Windows Store Profile subset
• Some WinRT components are brokered
– Capabilities are as a sort of "privilege elevation"
obtained with Brokered objects
– Contracts are a modern IPC mechanism
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile Runtime Security Broker
Kernel services
WinRT
Runtime Security Broker
Filtered COM / Win32 APIs Full COM / Win32
Comp.
Device access
Picker Host …
Comp.
Brokered UI AppContainer
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• How to avoid capabilities forgery?
– Native code has full power in its own process
• Assigned SIDs
– One SID to identify the application
– One SID for every requested capability
Capabilities under the hood
Compile time Windows
Store
Package Package
Code signing
Package
Runtime execution
Manifest SID assignement
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Development &
Mobile
• WinRT expose the OS in an OOP fashion
• Projections hide most of the complexity
• C++ and WRL are a good way to explore
what is behind
• Understanding the platform details can be of
great help while developing
Takeaways
itcampro @ itcamp13 # Premium conference on Microsoft technologies
Q & A
Thank you!