Your SlideShare is downloading. ×
2008 07 31 Understanding and Using COM Threading Model - An Inconvenient Truth and Nightmare of Marshalling
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

2008 07 31 Understanding and Using COM Threading Model - An Inconvenient Truth and Nightmare of Marshalling

3,133
views

Published on

Published in: Technology

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,133
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
58
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Understanding and Using COM Threading Model Recording Engine, DDR Team James S. Hsieh [email_address] An Inconvenient Truth and Nightmare of Marshalling
  • 2.
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
    Agenda
  • 3. 1. COM Threading Models
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
  • 4. What is COM: Component Object Model Technologies?
    • Component Object Model ( COM ) is a Microsoft centric interface standard for software componentry introduced by Microsoft in 1993 . OLE 1991 COM+ 2000
    • COM as an object framework
          • Programming Language Independent Object Model (IDL, Binary level layout)
          • Abstraction and Object Independent (Interface and Reference Counting)
          • Reflection (IDL, Type Library, and Automation)
          • Interprocess Communication , Location Transparency (IDL, Marshalling, Proxy and Stub, ORPC)
          • Type and Object Binding (Moniker)
          • Dynamic Object Creation, Serialization
    COM Client needs know .NET Managed Code C#, VB .NET… Runtime Callable Wrapper Native Code C/C++… COM Binary Protocols Native Code C/C++… COM Callable Wrapper .NET Managed Code C#, VB .NET… Implemented by Invoker COM Object framework
  • 5. What is Thread Safety?
    • Thread Safety
    • Thread safety is a computer programming concept applicable in the context of multi-threaded programs. A piece of code is thread-safe if it functions correctly during simultaneous execution by multiple threads.
    • In particular, it must satisfy the need for multiple threads to access the same shared data, and the need for a shared piece of data to be accessed by only one thread at any given time.
    • Thread Safety Level
    • Function Level example: Global function in C Runtime Library
    • Instance Level example: File handle in Win32 API
    • Transaction Level example: Atomic Transaction in Database
    COM Client needs know Thread ≡ People A Short Guide to Mastering Thread-Safety http://www.thinkingparallel.com/2006/10/15/a-short-guide-to-mastering-thread-safety/
  • 6. COM Assumption about Thread Safety COM Assumption about Threading Issues
    • A COM client can not know whether a COM server is thread safety. (including it’s threading model)
    • Any COM client can access any COM server in anytime anywhere.
    • In design principle, threading issues is server’s problem not client.
    COM Assumption: All COM Server must be thread safety Synchronization on a per-call basis (Instance Level) COM Client needs know
  • 7. Apartment Model Microsoft provides “Apartment Model” to reduce complexity of COM Thread Safety !? Another reason is that COM (OLE1 1991) did not support Multithreading in Microsoft Windows 3.0 (only Cooperative or Non-preemptive multitasking), but it (COM, OLE2) supported that in Microsoft Windows NT 3.5 and Windows 95 . Classify Belong Invoke COM Object (COM Server) Invoker Thread (COM Client) Apartment (Management Model)
  • 8. Apartment Models with Client Thread (1/2)
    • What is Apartment? Apartment is a Property of a COM thread stored in Thread-Local Storage , you can set/reset the property by COM API or Thread Class of .NET Framework. This attribute must be present on the entry point of any application that uses .NET Windows Forms, WPF or UI-oriented COM objects (ActiveX Control).
      • Single-threaded Apartment model (STA) [ 1 : 0 ~ n : 1 Process: STA : Thread] available in Windows NT 3.51
      • Multi-threaded Apartment model (MTA) [ 1 : 0 ~ 1 : n Process: MTA : Thread] available in Windows NT 4.0 and Windows 95
      • Neutral Apartment (NA ) [ 1 : 1 : 0 Process: NA : Thread] available in Windows 2000
    COM Client needs know To set apartment property is thread creator’s responsibility.
  • 9. Apartment Models with Client Thread (2/2) STA 0 STA 1 MTA NA Window Message Pumping STA n Process 1 Share one Apartment COM Client needs know Apartment Boundary NA STA ≡ Room MTA ≡ Dorm NA ≡ Tea Room Classify Room Room Room Dorm Tea Room … Apartment (Management Model) Invoker Thread (COM Client)
  • 10.
        • What is COM Threading Model? Threading Model is a Property of a COM Server
        • COM Implementer can choice one and only one threading model to implement COM Server in design-time. But, it can not be changed in runtime.
    • Implementer does not handle all threading issues
      • Implementer does not consider the threading issues in COM Object and Module .
          • Single Thread Model ( Single s upports STA 0 )
      • Implementer does not consider the threading issues in COM Object only . The implementer must synchronize access to any global variables, DllGetClassObject and DllCanUnloadNow .
          • Apartment Thread Model ( Apartment supports multi-STAs )
    • Implementer MUST handle all threading issues in COM Object and Module
          • Free Thread Model ( Free supports MTA )
          • Both Model ( Both supports multi-STAs and MTA )
          • Neutral Model ( Neutral supports NA )
    Threading Models with COM Server (1/4) COM Client needs know Module global variables Create Access Object Process
  • 11. Threading Models with COM Server (2/4) COM Server ≡ Oven COM Client needs know Belong STA 0 STA 1 MTA NA STA n Process Apartment Boundary NA Neutral Model Free, Both Model Single, Apartment , Both Model Apartment, Both Model … COM Object (COM Server) Apartment (Management Model)
  • 12. Threading Models with COM Server (3/4)
  • 13. Threading Models with COM Server (4/4)
    • The threading model is a Property of COM Server , the information is only stored in resource of COM binary and described only in registry and manifest .
    Registry SxS M anifest for COM Server HKEY_CLASSES_ROOTCLSID< Subkey > COM Client needs know Default is Single when T hreadingModel value not present
  • 14. Threading Models and Apartment Models (1/4)
    • General guidelines for participating threads and objects
      • A COM thread is also associated with an apartment ( STA or MTA ). (a thread in which COM objects are created or COM method calls are made)
      • Each COM object is associated with one and only one apartment ( STA, MTA, or NA, not thread).
      • Method calls which are made inside the same apartment are performed directly without any assistance from COM. The key-points: Threading safety of Single and Apartment model is based on this guidelines.
      • Method calls made across apartments are achieved via marshalling. Please refer “Mixed Model Development”
    COM Client needs know
  • 15. Threading Models and Apartment Models (2/4) NA the same apartments STA 0 STA 1 MTA STA n Process 1 NA Single Apartment Single Apartment Both Neutral Oven Tea Room Room Room Dorm People COM Client needs know Room Invoke Apartment Boundary 3. All calls to the COM object must be made on its thread (within its apartment). … Free Both COM Object (COM Server) Invoker Thread (COM Client) Apartment (Management Model)
  • 16. Threading Models and Apartment Models (3/4) COM Client needs know What thing is happened when COM Server is created in in compatible apartment (Cross Apartment)? 4. Method calls made across apartments are achieved via marshalling COM Server Threading Models Client Thread Apartment model COM Server associated in Single STA If thread is STA0 , COM object will be created in STA0. If it is not … (I ncompatible apartment) MTA (I ncompatible apartment) Apartment STA Client STA MTA (I ncompatible apartment) Free STA (I ncompatible apartment) MTA MTA Both STA Client STA MTA MTA Neutral STA/MTA NA (I ncompatible apartment)
  • 17. Threading Models and Apartment Models (4/4) NA cross apartments STA 0 STA 1 MTA STA n Process 1 NA Single Apartment Free Both Single Apartment Both Neutral Oven Tea Room Dorm Dorm Room People COM Client needs know Dorm Apartment Boundary illegal 4. Method calls made across apartments are achieved via marshalling What thing is happened when COM Server is accessed by incompatible thread (Cross Apartment)?
  • 18. 2. Mixed Model Development
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
  • 19.
      • Method calls made across apartments are achieved via marshalling.
      • Why? Microsoft provides Marshalling technique to resolve two problems
      • Let Single and Apartment COM Server thread safety, the designer does not consider threading issue during implementation.
      • COM is designed to allow clients to communicate transparently with objects, regardless of where those objects are running. (EX: DirectShow Graph Edit opens running graph by DOT)
    Mixed Model Development COM Server ≡ Phone COM Client needs know Apartment Another Apartment Channel Serialize arguments Unserialize arguments Proxy Stub across apartments Concept of Marshalling Pass serialized arguments by value except interface
  • 20. Concept of Marshalling (1/3) Problem 1: Serialize -> 1 Consumer- N Producer: queue and loop Let Single and Apartment COM Server thread safety in different apartment, Marshalling technique will serialize all method calls which are accessed by cross or owner threads. Serialize -> 1 Consumer- N Producer: queue and loop Process 1 Other Apartment STA Proxy Stub Queue Invoker thread thread which creates COM Server Thread Safety Key-Point : Every object lives on a single thread. All calls to an object must be made on its thread (within its apartment). It is forbidden to call an object directly from another thread. Microsoft reuses Message Loop and Hidden Window to process invocation from different apartment in STA. push Single Apartment Apartment Boundary Dispatch Message Accesses are serialized Pass serialized arguments by value (basically) with Message Queue Direct call by stack
  • 21. Concept of Marshalling (2/3) Each apartment/thread with objects in it must have a message queue in order to handle calls from other processes and apartments within the same process. This means simply that the thread's work function must have a GetMessage/ DispatchMessage loop. (Include .NET managed code, Win Form and WPF ) COM Client needs know PS. You can monitor the message via Spy++. Get arguments Invoke COM Object
  • 22. Concept of Marshalling (3/3)
      • Cross process -> Client-Server: socket, listen thread and worker thread
    Process 1 Process 2 Proxy Stub Listen thread Worker thread The thread is created by COM Runtime. Invoker thread Pass serialized arguments by value (basically) with LPC/IPC, RPC, Other… Direct call by stack Dispatcher Process or Machine Boundary different memory address space Apartment Problem 2: Cross Boundary Key-Point: All arguments need be serialized to cross boundary. COM is designed to allow clients to communicate transparently with objects, regardless of where those objects are running. Microsoft ORPC Runtime Apartment TCP UDP IPX SPX HTTP “ Falcon” Protocol Stack (Pluggable Transports) Accesses are not serialized. Cross process -> Client-Server: socket, listen thread and worker thread
  • 23. Mixed Model Development of in-process Marshalling Apartment Boundary Process STA 1 STA 0 Proxy Stub MTA NA Queue Worker thread Dispatch Message Case 1 Invoker thread thread which creates COM Server COM Runtime push Free Both Neutral Single, Apartment Both Stub Stub Dispatcher Invoker thread Pass serialized arguments by value (basically) with Shared memory, LPC/IPC, RPC, Other… Direct call by stack Create Thread like Case 2 Thread Pool Listen thread
  • 24. Mixed Model Development of out-process Marshalling MTA Process 1 ?A Process 2 Proxy Dispatcher Worker thread Case 2 Pass serialized arguments by value (basically) with Shared memory, LPC/IPC, RPC, Other… Direct call by stack STA 0 Stub Queue thread which creates COM Server NA push Neutral Free Both COM Runtime Stub Stub Invoker thread Create Thread Process or Machine Boundary Single Apartment Both Worker thread Dispatch Message Apartment Boundary like Case 2 Case 1 Thread Pool Listen thread Worker thread
  • 25. Creating COM Server in Mixed-Apartment case COM Client needs know COM Runtime will handle all incompatible case Automatically . COM Server Threading Models Client Thread Apartment model Get COM Object pointer from CoCreateInstance COM Server associated in Single STA If(thread is STA0) direct pointer else proxy pointer If thread is STA0 , COM object will be created in STA0. If it is not, COM Runtime will create a STA0 thread (with a message pumping) to create and service the COM object (Cross apartment). MTA proxy pointer If STA0 exists, COM object will be created in STA0. If it is not, COM Runtime will create a STA0 thread (with a message pumping) to create and service the COM object (Cross apartment). Apartment STA direct pointer Client STA (Wish the thread has a message pumping) MTA proxy pointer COM Runtime will create a STA thread (with a message pumping) to create and service the COM object (Cross apartment). Free STA proxy pointer COM Runtime will create a MTA thread in thread pool (without a message pumping) to create the COM object (Cross apartment). MTA direct pointer MTA Both STA direct pointer Client STA (Wish the thread has a message pumping) MTA direct pointer MTA Neutral STA/MTA proxy pointer NA (Cross apartment)
  • 26. Accessing COM Server in Mixed-Apartment case NA cross apartments STA 0 STA 1 MTA STA n Process 1 NA Single Apartment Free Both Single Apartment Both Neutral Oven Tea Room Dorm Dorm Room People COM Client needs know Dorm Apartment Boundary Apartment Another Apartment Channel Serialize arguments Unserialize arguments Proxy Stub across apartments Concept of Marshalling How can I create Proxy and Stub of COM server Manual ly ?
  • 27. 3. COM Interface Marshalling and Unmarshlling
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
  • 28.
    • General guidelines
    • Proxy and Stub of COM Server are created by Interface Marshalling / Unmarshlling procedures.
    • The Interface Marshalling / Unmarshlling procedures can be Automatic in some case or Manual by COM client.
    • The Interface Unmarshlling procedure will decide the returned interface pointer is direct pointer or proxy pointer by apartment context .
    • To create Proxy and Stub of COM Server manually is Client’s responsibility when a thread accesses a COM Server which is associated different Apartment with caller thread. In .NET managed code, the RCW will handle that automatically, but the proxy and stub will NOT be created automatically in native codes (C/C++).
    Interoperability: How to create Proxy of COM Server COM Client needs know
  • 29.
    • Auto Marshalling: COM Runtime and Proxy will handle that.
          • CoCreateInstance , CoCreateInstanceEx , CoGetClassObject , Dynamic Creation CoGetInstanceFromFile , and CoGetInstanceFromIStorage , will return a proxy when client thread is in incompatible apartment .
    Auto Marshalling (1/2) COM Client needs know COM Server Threading Models Client Thread Apartment model Get COM Object pointer COM Server associated in Single STA 1 ~ n proxy pointer COM Runtime will create a STA0 thread (with a message pumping) to create and service the COM object (Cross apartment). MTA proxy pointer COM Runtime will create a STA0 thread (with a message pumping) to create and service the COM object (Cross apartment). Apartment MTA proxy pointer COM Runtime will create a STA thread (with a message pumping) to create and service the COM object (Cross apartment). Free STA proxy pointer COM Runtime will create a MTA thread (without a message pumping) to create the COM object (Cross apartment). Neutral STA/MTA proxy pointer NA (Cross apartment)
  • 30.
    • Auto Marshalling: COM Runtime and Proxy will handle that.
          • Any direct pointer pass in/return from a function by proxy , the direct pointer will be auto marshaled by proxy or direct pointer according to apartment context .
    Auto Marshalling (2/2) COM Client needs know Apartment Another Apartment Channel y Serialize arguments Unserialize arguments Proxy of y Stub of y across apartments Concept of Marshalling x x->xxx() y->Function1(x) Imp. Function1 Direct call by stack Proxy of x Stub of x
  • 31.
    • Manual Marshalling: COM Runtime provides several methods to create proxy via marshalling an interface, these method can return proxy or direct pointer of COM object according to apartment context automatically.
            • Low Level : For all in-process, out-of-process, and cross-machine case: CoMarshalInterface, CoUnmarshalInterface
            • High Level: For in-process case: CoMarshalInterThreadInterfaceInStream, CoGetInterfaceAndReleaseStream
            • Optimization : For optimization for in-process : IGlobalInterfaceTable CLSID_StdGlobalInterfaceTable
    Manual Marshalling (1/3) COM Client needs know The .NET RCW will handle in-process case automatically.
  • 32. Manual Marshalling (2/3) STA 1 Invoker thread STA 0 Stub Message Queue push Apartment Both Dispatch Message Marshal Unmarshal Proxy Process Pass serialized arguments by value (basically) with Shared memory, LPC/IPC, RPC, Other… Direct call by stack Manual Marshalling 1 – Can handle all scenario Apartment Boundary Invoker thread Owner thread Get Proxy Create Stub COM Client needs know stream
  • 33. Manual Marshalling (3/3) Manual Marshalling 2 – Can m arshal interface in-process only Invoker thread Owner thread Get Proxy Create Stub COM Client needs know
  • 34. 4. COM Client Case Studies
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
    Must have Message Loop when STA thread shares COM object Must Interface Marshalling when cross thread accessing
  • 35.
    • Nightmare of Marshalling - Episode 1-1
          • An Apartment COM Server is created in STA thread 0. (will get direct pointer)
          • The STA thread 0 passes the direct pointer to a STA/MTA thread 1 without Manual Marshalling. (The behavior is not according with COM convention)
          • The STA thread 1 calls the function of COM object via direct pointer, it is not thread safety , but it is callable (you will never get error code in this scenario), Horrible !!
    Nightmare of Marshalling (1/8) Process STA 1/ MTA STA 0 Unsafe COM Client needs know Single Apartment Both The proxy and stub will NOT be created automatically
  • 36.
    • Nightmare of Marshalling - Episode 1-2
    Nightmare of Marshalling (2/8) COM Client needs know STA MTA Channel y Serialize arguments Unserialize arguments Proxy of y Stub of y across apartments x Channel Proxy of x Stub of x STA MTA y Proxy x Unsafe across apartments Hold pointer Hold pointer
  • 37.
    • Nightmare of Marshalling - Episode 2
          • An Free COM Server is created in STA thread 0. (will get proxy)
          • The STA thread 0 passes the pointer to a STA thread 1 without Manual Marshalling. (The behavior is not according with COM convention)
          • The STA thread 1 will get error code RPC_E_WRONG_THREAD when it calls the function of COM object via proxy. Thanks GOD, the bug is easy to find, but it is difficult to fix !!
          • You will get assess violation when threading model of COM object is Neutral.
          • Key-Point: The proxy is associated with one apartment only.
    Nightmare of Marshalling (3/8) Process STA 0 STA 1 MTA Proxy Stub RPC_E_WRONG_THREAD COM Client needs know
  • 38. Do we need Marshalling in PURE C++ environment !? COM Client needs know Without/With interfaceMarshalling TS = Thread Safty ML = Message Loop ORPC = object remote procedure call Owner Thread Invoker Thread Single COM Apartment COM Both COM Both COM with FreeThreadedMarshaler Free COM Neutral COM Thread Safety technique Marshalling argument by ML Marshalling argument by ML COM server itself* COM server itself* COM server itself COM server itself STA 0 Other STA Work, not TS Episode 1-1 Work, not TS Episode 1-1 Work, but … Episode 1-2 Work* Created in MTA/ NG PC_E_WRONG_THREAD Episode 2 NG* Episode 2 Created in STA 0 / Marshalling with ML Marshalling with ML Marshalling with ML Direct* Created in MTA / Marshalling with ORPC Direct* STA 1 ~ n Other STA Created in STA 0/ NG PC_E_WRONG_THREAD Episode 2 Work, not TS Episode 1-1 Work , but … Episode 1-2 Work* Created in MTA/ NG PC_E_WRONG_THREAD Episode 2 NG* Episode 2 Created in STA 0 / Marshalling with ML Marshalling with ML Episode 1 Marshalling with ML Direct* Created in MTA / Marshalling with ORPC Direct* MTA Created in STA 0/ NG PC_E_WRONG_THREAD Episode 2 Work, not TS Episode 1-1 Work , but … Episode 1-2 Work* Created in MTA/ NG PC_E_WRONG_THREAD Episode 2 NG* Episode 2 Created in STA 0 / Marshalling with ML Marshalling with ML Marshalling with ML Direct* Created in MTA / Marshalling with ORPC Direct* MTA STA Created in STA 0/ NG PC_E_WRONG_THREAD Episode 2 Created in STA/ NG PC_E_WRONG_THREAD Episode 2 Work , but … Episode 1-2 Work* Created in MTA/ NG PC_E_WRONG_THREAD Episode 2 NG* Episode 2 Created in STA 0 / Marshalling with ML Marshalling with ML Marshalling with ORPC Direct* Created in MTA / Marshalling with ORPC Direct* MTA Created in STA 0/ NG PC_E_WRONG_THREAD Episode 2 Created in STA/ NG PC_E_WRONG_THREAD Episode 2 Work* Work* Work* NG* Episode 2 Created in STA 0 / Marshalling with ML Marshalling with ML Direct Direct* Direct Direct* To out of process or remote process NG NG NG NG NG NG Marshalling with ORPC Marshalling with ORPC Marshalling with ORPC Marshalling with ORPC Marshalling with ORPC Marshalling with ORPC
  • 39.
    • Nightmare of Marshalling - Episode 3
          • An Apartment COM Server is created in STA thread 0 but the thread without message loop . (The behavior is not according with COM convention)
          • The STA thread 0 passes the COM object to a STA/MTA thread 1 with Manual Marshalling.
          • The STA/ MTA thread 1 calls the function of COM object via proxy. Block , Block, Block !!
    Nightmare of Marshalling (4/8) Process STA 0 STA 1/MTA Proxy Stub ? Block COM Client needs know Single Apartment Both
  • 40.
    • Nightmare of Marshalling - Episode 4 All behaviors are according with COM convention
          • An Apartment COM Server is created in STA thread 0 and, the thread is UI thread (it has message loop).
          • Purpose: The invocation does not block thread 0 to refresh UI. The STA thread 0 passes the COM object to a STA/MTA worker thread 1 with Manual Marshalling.
          • The STA/MTA thread 1 calls the function of COM object via proxy, but stub will call STA thread 0 to serve the invocation. thread 0 is busy, it can not refresh UI !! It maybe is COM server’s problem. Please refer “ Choosing the Threading Model”
    Nightmare of Marshalling (5/8) UI STA 0 STA 1/MTA Stub Proxy 1 2 3 4 Process Busy COM Client needs know Single Apartment Both
  • 41. Nightmare of Marshalling (6/8) STA 0 STA 1/MTA Proxy Stub ? WAIT WAIT Nightmare of Marshalling - Episode 5 Deadlock !! Process Deadlock COM Client needs know
  • 42. Nightmare of Marshalling (7/8) STA 0 STA 1/MTA Proxy Stub WAIT and Check WAIT Solution of Episode 5 Replace WaitForSingleObject to Wait WaitWithMessageLoop Process Deadlock-free!! COM Client needs know
  • 43.
    • Nightmare of Marshalling - Episode 6
    • Marshalling Interface mechanism is based on Apartment property of current thread (from TLS) and proxy (not COM object) to decide whether the Apartment context is compatible. The meaning is that you can let Marshalling Interface mechanism confound with following scenario.
          • An Apartment COM Server is created in STA thread 0. (will get direct pointer)
          • The STA thread 0 passes the direct pointer to a STA thread 1 without Manual Marshalling. (The behavior is not according with COM convention)
          • The STA thread 1 passes the COM object to a STA/MTA thread 2 with Manual Marshalling. (The Marshalling Interface mechanism will decide the owner of COM object is STA thread 1 but it is wrong, the correct is thread 0, Kidding !! )
    • In .NET Framework , the RCW (runtime-callable wrapper) will handle to create the proxy automatically, but if your code is mix native and managed code such as PInvoke to pass COM Interface and C++/CLI, the all native code must follow COM convention to pass a proxy interface cross apartment, otherwise … 
    Nightmare of Marshalling (8/8) Process STA 0 STA2 / MTA STA 1 Proxy Stub To be continued Unsafe , Kidding COM Client needs know
  • 44.
    • You can create many nightmares if COM Client or Server does not follow COM Marshalling Convention .
    Nightmare of Marshalling Nightmare To Be Continued !! Caution !!
  • 45. 5. Inside Standard Marshalling
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
  • 46. Inside Standard Marshalling (1/5) Other Apartment Pass serialized arguments by value (basically) with Shared memory, LPC/IPC, RPC, Other… Arguments pass by stack ITest Apartment Boundary Apartment ITest Apartment Another Apartment Channel Serialize arguments Unserialize arguments Proxy Stub across apartments Concept of Marshalling Marshalling has two key-components COM Object IUnknown Invoke ORPC Channel IRpcChannelBuffer Connect ORPC Channel IRpcChannelBuffer Object Proxy Manager IUnknown SendReceive GetBuffer IUnknown Object Stub Manager ORPC IRpcProxyBuffer Interface ITest Proxy Marshalling arguments Interface ITest Stub IRpcStubBuffer U nmarshalling arguments
  • 47. Inside Standard Marshalling (2/5)
    • Marshalling has two key-components
    • Object Proxy Manager and Stub Manager (Object level) The Object Proxy and Stub are associated with COM object , it provide life control and channel management between two apartments.
    Create Create Connect
    • Standard Marshaler (OLE32.DLL provided by Microsoft )
    • Custom Marshaler (COM server implements IMarshal Interface and handles all Marshalling issues)
    • Marshaler creates Object Proxy Manager and Stub Manager during Interface Marshalling and Unmarshalling procedures (CoMarshalInterface, CoUnmarshalInterface …)
    • Object Proxy Manager and Stub Manager create and connect RPC Channel (IRpcProxyBuffer IRpcStubBuffer, and IRpcChannelBuffer) between proxy and stub
    Standard Marshaler IMarshal Object Proxy Manager Object Stub Manager ORPC Channel
  • 48. Inside Standard Marshalling (3/5)
    • If the Interface is provided by Microsoft , the interface Proxy and Stub is implemented in OLE32.DLL and Microsoft’s DLL.
    • If COM Server is OLE Automation interface (has property oleautimation in interface of IDL) and it accords with Automation protocol. The COM Server don’t need implement Interface Proxy and Stub, but register TLB is necessary to use Universal Marshaler .
    • If the interface is Custom Interface , the source code of Interface Proxy and Stub is generated by MIDL compiler. It can be merged to COM DLL or separated to Proxy DLL. Caution !! The Interface Proxy and Stub is necessary.
    • Marshalling has two key-components
    • Interface Proxy and Stub (Interface level) The Interface Proxy and Stub are associated with Interface not COM object, it only focus on arguments marshalling, unmarshalling and reconstruct call stack in function of interface.
    {00020424-0000-0000-C000-000000000046} Marshalling arguments Unmarshalling arguments across apartments Create Create Interface Proxy Interface Stub PSFactory Object IPSFactoryBuffer
  • 49. Inside Standard Marshalling (4/5) Implemented by MIDL in Proxy.DLL Implemented by OLE32.DLL Marshalling has two key-components Interface X 2) Interface Proxy and Stub 1) Object Proxy Manager and Stub Manager Implemented by MIDL in COM.DLL
    • The Proxy DLL must be registered in registry or manifest .
    COM Object IUnknown ORPC Channel IRpcChannelBuffer Object Proxy Manager IUnknown IUnknown Object Stub Manager Standard Marshaler IMarshal Interface Stub IRpcStubBuffer PSFactory Object IPSFactoryBuffer IRpcProxyBuffer Interface Proxy Interface X
  • 50. Inside Standard Marshalling (5/5) Other Apartment Pass serialized arguments by value (basically) with Shared memory, LPC/IPC, RPC, Other… Arguments pass by stack ITest Proxy Stub Apartment Boundary Apartment Relationship ITest CoMarshalInterface Co Unm arshalInterface Implemented by MIDL in Proxy.DLL Implemented by OLE32.DLL COM Object IUnknown Invoke ORPC Channel IRpcChannelBuffer Create and manage COM Aggregate* Connect ORPC Channel IRpcChannelBuffer Create and manage Object Proxy Manager IUnknown SendReceive GetBuffer IUnknown Object Stub Manager ORPC PSFactory Object IPSFactoryBuffer Life control Interface and Life control bind by IID bind by IID IRpcProxyBuffer Interface ITest Proxy Marshalling arguments Standard Marshaler IMarshal Create Create Create Create connect Interface ITest Stub IRpcStubBuffer U nmarshalling arguments stream
  • 51. How to bind Interface Proxy and Stub (1/2) Interface Proxy and Stub Factory HKEY_CLASSES_ROOTCLSID< Subkey > Interface Proxy and Stub relation info HKEY_CLASSES_ROOTInterface< Subkey > 1. From registry PSFactory Object IPSFactoryBuffer
  • 52. How to bind Interface Proxy and Stub (2/2) SxS M anifest for Interface Proxy and Stub 2. From Manifest Registration-Free Activation of COM Components: A Walkthrough http://msdn.microsoft.com/en-us/library/ms973913.aspx Get CLSID via export function GetProxyDllInfo . PSFactory Object IPSFactoryBuffer
  • 53. How to implement Interface Proxy and Stub (1/3)
      • The source code of Interface Proxy and Stub is generated by MIDL Compiler.
    • What is Microsoft Interface Definition Language?
      • MIDL defines interfaces between client and server programs in interface definition language (IDL) files required for remote procedure call (RPC) interfaces and COM/DCOM interfaces .
      • To define programming language independent Interface (IDL file)
      • To generate programming language dependent definition (C/C++: Header file)
      • To generate Interface Metadata (Type Library, TLB file)
      • To generate source code of Interface Proxy and Stub
    MIDL is key-point to generate correct interface proxy and stub.
  • 54. How to implement Interface Proxy and Stub (2/3) Separate and Merge Proxy and Stub to COM Server binary Project.lib Project_i.c Generated Files MIDL Compiler Midl.exe Project Files include include Implement of interface Proxy and Stub Metadata of COM Server Interface definitions in C/C++ CLSID/IID definitions The proxy/stub file, which includes the surrogate entry points both for clients and for servers. Contains the data you need to create a proxy/stub DLL. C/C++ Compiler and Linker Others Project.DLL ProjectPS: If proxy is separated COM Server binary ProjectPS.DLL Interface Proxy and Stub Link in RC Implement PSFactory Object C/C++ Compiler and Linker If proxy is merged Project.idl Project.h Project.tlb Project_p.c Dlldata.c Dlldatax.c
  • 55. Merge Proxy and Stub to COM Server binary Dlldatax.c Project.cpp In merge proxy case, the proxy will be registered during COM registering. In separate proxy case, the projectPS.DLL or other proxy DLL which implements the same interface MUST be registered , otherwise the CoMarshalInterXXX function and auto marshalling will not work and return error code E_NOINTERFACE . How to implement Interface Proxy and Stub (3/3)
  • 56. IDL Interface Design Rules (1/2)
    • Interface
    • A interface must have a unique interface identifier (IID). IID of Interface Proxy and Stub conflict problem
    • A interface must be immutable. Once they are created and published, no part of their definition may change. Interface Proxy and Stub conflict problem
    • The current implementation of MIDL does not handle function overloading or multiple inheritance.
  • 57. IDL Interface Design Rules (2/2)
    • Function
    • All interface methods must return an HRESULT so that the portions of the system that handle remote processing can report RPC errors.
    • Your data types must be remotable
      • If you cannot convert a data type to a remotable type, you will have to create your own marshaling and unmarshaling routines. Also, LPVOID, or void *, has no meaning on a remote machine. Use a pointer to IUnknown, if necessary.
        • Key-points:
          • Portable Type (ex: HWND, HANDLE, LPVOID … are not acceptable)
          • Non-reference value (except interface)
          • Well define-size (except interface)
    • All string parameters in interface methods must be Unicode. 
  • 58. FreeThreaded Marshaler
    • That way the client receives a real live pointer to the object. The client talks to the object directly without having to go through proxies and stubs in in-process case.
    • Great care should be exercised in using the CoCreateFreeThreadedMarshaler function. This is because the performance of objects which aggregate the free-threaded marshaler is obtained through a calculated violation of the rules of COM, with the ever-present risk of undefined behavior unless the object operates within certain restrictions. The most important restrictions are:
    • A free-threaded marshaler object cannot hold direct pointers to interfaces on an object that does not aggregate the free-threaded marshaler as part of its state. If the object were to use direct references to ordinary single-threaded aggregate objects, it may break their single threaded property. If the object were to use direct references to ordinary multi-threaded aggregate objects, these objects can behave in ways that show no sensitivity to the needs of direct single-threaded aggregate clients. For example, these objects can spin new threads and pass parameters to the threads that are references to ordinary single-threaded aggregate objects.
    • A free-threaded marshaler object cannot hold references to proxies to objects in other apartments. Proxies are sensitive to the threading model and can return RPC_E_WRONG_THREAD if called by the wrong client.
  • 59. 6. COM Server Side Case Studies
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
    Must implement and register Interface Proxy and Stub Must understand Semantic of IDL and define correct Interface
  • 60. Nightmare of Marshalling (1/6) Nightmare of Marshalling – Episode 7
      • Forget to register Interface Proxy, Stub and Typelib in registry or manifest.
      • You will get error code from CoCreateInstance , CoMarshalInterface and CoMarshalInterThreadInterfaceInStream REGDB_E_IIDNOTREG (0x80040155) “ Interface not registered ” E_NOINTERFACE ( 0x80004002 ) “ No such interface supported ”
      • E_INVALIDARG (0x80070057) “ One or more arguments are invalid ” ( Neutral COM Server Case )
      • TYPE_E_LIBNOTREGISTERED (0x80070057) “ The type library is not registered ” ( Universal Marshaler Case )
      • Register incorrect or incompatible Interface Proxy and Stub in registry or manifest. You will get crash in rpcrt4.dll, ole32.dll or ntdll.dll… or get invalid argument during function call or function return.
      • To registry COM Server will write default value in ProxySubClsid32 (Universal Marshaler). BUT the Universal Marshaler CAN NOT work with custom interface usually.
    {00020424-0000-0000-C000-000000000046}
  • 61. Nightmare of Marshalling (2/6) Nightmare of Marshalling - Episode 8
      • Use pointers to data very carefully . To re-create the data in the address space of the process that is called, the RPC run time must know the exact size of the data. Please use size_is , length_is, and max_is to specify size. If, for example, a CHAR * parameter points to a buffer of characters rather than to a single character , the data cannot be correctly re-created. Use the syntax available with MIDL to accurately describe the data structures represented by your type definitions.
      • You will get crash in rpcrt4.dll, ole32.dll or ntdll.dll… or get invalid argument during function call or function return.
  • 62. Nightmare of Marshalling (3/6) Nightmare of Marshalling – Episode 9 Will not Marshal interface automatically
      • Use pointers to Interface very carefully.
      • To create the COM Proxy and Stub in the address space of the process that is called (Interface Marshalling), the RPC run time must know the interface type of the interface pointer. Please use iid_is , to specify IID.
      • You will get interface pointer without proxy and stub but the proxy and stub is necessary. Please recall  Nightmare of Marshalling – Episode 1-2.
  • 63. Nightmare of Marshalling (4/6) Nightmare of Marshalling - Episode 10 (1/3) What is the value result? 1, 2 or ??? COM Interface COM Client PS. The pTest is proxy pointer. COM Server Aliasing p1 p2 m1 p1 p2 m2 m3 p1 p2 m2 unique ptr Pointer Attribute unique ptr pPtr1 and pPtr2 To point different address , the two values are 0. To point the same address , the value is 0.
  • 64. Nightmare of Marshalling (5/6) Nightmare of Marshalling - Episode 10 (2/3)
      • Be careful when argument is pointer and one of the following conditions is established.
        • You DO NOT understand what meaning of the pointer attribute. You can use ref, unique, and ptr to specify pointer argument and struct.
        • Allocate/Relocate memory in COM Server, and pass it to client.
        • Orphan client’s memory reference in COM Server.
        • Aliasing memory reference.
      • The general rules for the manipulation of marshalled parameter data are simple:
        • The server can only allocate new memory or modify the memory specifically allocated by the server stub.
        • Reallocating or releasing existing memory for data can have a negative impact on the results and performance of the function call, and can be very difficult to debug.
  • 65. Nightmare of Marshalling (6/6) Nightmare of Marshalling - Episode 10 (3/3) Characteristics Attribute of Pointer ref (default) unique ptr Can have the NULL pointer. No Yes Yes To describe the size of an array or union Yes No No Can change the storage Yes [out, ref] Yes [in, out, unique] Yes [in, out, ptr] Can change the pointer No Yes [in, out, unique] Yes [in, out, ptr] (NULL to non-NULL in COM Server) Can allocate new memory on the client. n/a Yes [in, out, unique] Yes [in, out, ptr] (Non-NULL to NULL in COM Server) Can orphan memory on the client. n/a Yes [in, out, unique] Yes [in, out, ptr] Can use existing memory on the client without allocating new memory. n/a Yes [in, out, unique] Yes [in, out, ptr] (O ne non-NULL value to another in COM Server) Can relocate new memory on the client. Not recommend, because it is complex, server needs handle n/a No Yes [in, out, ptr] Aliasing ( reconvergence and cycles reference) No No Yes Overhead Low Middle High
  • 66. 7. Conclusion 
          • COM Threading Models
          • Mixed Model Development
          • COM Interface Marshalling and Unmarshlling
          • COM Client Case Studies
          • Inside Standard Marshalling
          • COM Server Side Case Studies
          • Conclusion
  • 67. Profiling of Proxy and Stub 100,0000 times function call, size of all argument is 44 bytes Do noting Profiling Single, Apartment and Both COM Server Free and Both COM Server Neutral COM Server The same Apartment 3 ms 3 ms N/A Cross Apartment Message Loop 22,472 ms Worker Thread 18,287 ms The same thread 1094 ms
  • 68. Choosing the COM Threading Model
    • Choosing the threading model for an object depends on the object's function.
    • Complexity of Implement (Single or Apartment) : Supporting the STA model is easier because COM runtime provides synchronization.
    • Maximum Response (Both, Free or Neutral) : MTA model is more difficult because the object must implement synchronization, but response to clients is better because synchronization is used for smaller sections of code , rather than for the whole interface call as provided by COM (Single and Apartment).
    • UI-Oriented (Single or Apartment) : This is necessary for UI-oriented COM objects, like controls and drag and drop, which must also be synchronized together with the UI .
    • Support Asynchronous Call (Both, Free or Neutral)
    • Overhead of Marshalling (Depend on context, Free)
  • 69.
    • You can create many nightmares if COM Client or Server does not follow COM Marshalling Convention .
    Caution !! Conclusion
    • Must have Message Loop when STA thread shares COM object
    • Must Marshal Interface when cross thread accessing
    • Must understand Semantic of IDL and define correct Interface
    • Must implement and register Interface Proxy and Stub
  • 70. Reference (1/5)
    • Reference-Counting Rules 1
    • Rule 1: AddRef must be called for every new copy of an interface pointer, and Release called for every destruction of an interface pointer, except where subsequent rules explicitly permit otherwise.
    • The following rules call out common nonexceptions to Rule 1.
      • Rule 1a: In-out-parameters to functions. The caller must AddRef the actual parameter, since it will be Released by the callee when the out-value is stored on top of it.
      • Rule 1b: Fetching a global variable. The local copy of the interface pointer fetched from an existing copy of the pointer in a global variable must be independently reference counted, because called functions might destroy the copy in the global while the local copy is still alive.
      • Rule 1c : New pointers synthesized out of &quot;thin air.&quot; A function that synthesizes an interface pointer using special internal knowledge, rather than obtaining it from some other source, must do an initial AddRef on the newly synthesized pointer. Important examples of such routines include instance creation routines, implementations of IUnknown::QueryInterface, and so on.
      • Rule 1d: Returning a copy of an internally stored pointer. After the pointer has been returned, the callee has no idea how its lifetime relates to that of the internally stored copy of the pointer. Thus, the callee must call AddRef on the pointer copy before returning it.
  • 71. Reference (2/5) Reference-Counting Rules 2 Rule 2: Special knowledge on the part of a piece of code of the relationships of the beginnings and the endings of the lifetimes of two or more copies of an interface pointer can allow AddRef/Release pairs to be omitted. From a COM client's perspective, reference-counting is always a per-interface concept. Clients should never assume that an object uses the same reference count for all interfaces. The return values of AddRef and Release should not be relied upon, and should be used only for debugging purposes. Pointer stability; see details in the OLE Help file under &quot;Reference-Counting Rules,&quot; subsection &quot;Stabilizing the this Pointer and Keeping it Valid.&quot;
  • 72. Reference (3/5)
    • Memory Management Rules 1
    • The lifetime management of pointers to interfaces is always accomplished through the AddRef and Release methods found on every COM interface. (See &quot;Reference-Counting Rules&quot; below.)
    • The following rules apply to parameters to interface member functions, including the return value, that are not passed &quot;by-value&quot;:
      • in parameters the caller should allocate and free the memory.
      • out parameters must be allocated by the callee and freed by the caller using the standard COM memory allocator.
      • in-out parameters are initially allocated by the caller, then freed and re-allocated by the callee if necessary. As with out parameters, the caller is responsible for freeing the final returned value. The standard COM memory allocator must be used.
  • 73. Reference (4/5)
    • Memory Management Rules 2
    • Another area that needs special attention is the treatment of out and in-out parameters in failure conditions. If a function returns a failure code, the caller typically has no way to clean up the out or in-out parameters. This leads to the following additional rules:
      • In case of an error condition, parameters must always be reliably set to a value that will be cleaned up without any action by the caller.
      • All out pointer parameters must explicitly be set to NULL. These are usually passed in a pointer-to-pointer parameter but can also be passed as members of a structure that the caller allocates and the called code fills. The most straightforward way to ensure this is (in part) to set these values to NULL on function entry. This rule is important because it promotes more robust application interoperability.
      • Under error conditions, all in-out parameters must either be left alone by the code called (thus remaining at the value to which they were initialized by the caller) or be explicitly set, as in the out parameter error return case.
    • Remember that these memory management conventions for COM applications apply only across public interfaces and APIs—there is no requirement at all that memory allocation strictly internal to a COM application need be done using these mechanisms.
    • COM internally uses Remote Procedure Calls (RPC) to communicate between clients and servers. For more information about managing memory in RPC server stubs, see the Server-stub Memory Management topic.
  • 74. Reference (5/5) Memory Management Rules 3
      • The server should not attempt to reallocate or release [in] data, leaving the control of those spaces to the RPC server stub itself.
      • Generally, the server function implementation does not need to reallocate or release data marked with the [in, out] attribute. For fixed size data, the function implementation logic can directly modify the data.
      • If circumstances occur where the server routine has to reallocate the memory used by data marked with the [in, out] attribute, it is entirely possible that the server-side function implementation will not know if the pointer provided by the stub is to memory allocated with MIDL_user_allocate() or the marshaled wire buffer. To work around this problem, MS RPC can ensure that no memory leak or corruption occurs if the [force_allocate] attribute is set on the data. When [force_allocate] is set, the server stub will always allocate memory for the pointer, although the caveat is that performance will decrease for every use of it.
      • Pay attention to how you allocate and free memory. Remember that, unless you explicitly tell a COM object (by using the allocate attribute) not to free a data structure that was created during an out-of-process call, that structure will be destroyed when the call completes. Also, consider the potentially destructive overhead created by inefficient allocation of data structures that now need to be marshaled and unmarshaled.
  • 75. Reference
    • Component Object Model (General) http://msdn2.microsoft.com/en-us/library/ms877981.aspx
    • Component Object Model, Part I http://graphcomp.com/info/specs/com/comch01.htm
    • Component Object Model, Part II http://graphcomp.com/info/specs/com/comch02.htm
    • Understanding and Using COM Threading Models (2004) http://msdn2.microsoft.com/en-us/library/ms809971.aspx
    • COM Macro Architecture Topology – Servers http://www.codeproject.com/KB/COM/macrotoposervers.aspx
    • COM IDs & Registry keys in a nutshell http://www.codeproject.com/KB/COM/mmtopo_comid.aspx
    • The COM Macro-Architecture Topology http://www.codeproject.com/KB/COM/macrotopomain.aspx
    • Inside COM (1997)
    • Inter-Object Communication http://msdn.microsoft.com/en-us/library/ms693719(VS.85).aspx
    • Essential COM (2000)
    • Standard Marshalling Architecture http://msdn.microsoft.com/en-us/library/ms810417.aspx
    • Descriptions and Workings of OLE Threading Models (2003) http://support.microsoft.com/kb/150777/en-us
    • OLE Threads Must Dispatch Messages (2005) http://support.microsoft.com/kb/136885/EN-US/
    • Understanding The COM Single-Threaded Apartment Part 1 (2005) http://69.10.233.10/KB/COM/CCOMThread.aspx
    • Understanding The COM Single-Threaded Apartment Part 2 (2005) http://69.10.233.10/KB/COM/CCOMThread2.aspx
    • Understanding Custom Marshalling Part 1 (2006) http://69.10.233.10/KB/COM/CustomMarshalling01.aspx
    • I nterface Marshalling http://msdn.microsoft.com/en-us/library/ms686605(VS.85).aspx
    • Choosing the Threading Model http://msdn2.microsoft.com/en-us/library/ms693779(VS.85).aspx
    • The Rules of the Component Object Model (1995) http://msdn2.microsoft.com/en-us/library/ms810016.aspx
    • Interface Design Rules http://msdn.microsoft.com/en-us/library/ms692709(VS.85).aspx
    • A natomy of an IDL File http://msdn.microsoft.com/en-us/library/ms690150(VS.85).aspx
    • MIDL Language Reference http://msdn2.microsoft.com/en-us/library/aa367088(VS.85).aspx
    • Remote Procedure Call (RPC) Programmer's Guide http://msdn.microsoft.com/en-us/library/aa374358(VS.85).aspx
    • Manifest Files Reference http://msdn.microsoft.com/en-us/library/aa375632(VS.85).aspx
    • Mark Windows Forms entry points with STAThread http://msdn.microsoft.com/en-us/library/ms182351.aspx (Thanks Jim)
    • Registration-Free Activation of COM Components: A Walkthrough http://msdn.microsoft.com/en-us/library/ms973913.aspx
    • Registration-Free Activation of . NET-Based Components: A Walkthrough http://msdn.microsoft.com/en-us/library/ms973915.aspx