{"id":106750,"date":"2022-06-14T07:00:00","date_gmt":"2022-06-14T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106750"},"modified":"2022-06-14T05:58:45","modified_gmt":"2022-06-14T12:58:45","slug":"20220614-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220614-00\/?p=106750","title":{"rendered":"What are the various usage patterns for manually-marshaled interfaces?"},"content":{"rendered":"<p>COM organizes threads into <i>apartments<\/i>. All the thread in an apartment have access to the same objects, and if you want to grant access to another apartment, you have to do it by a mechanism known as <i>marshaling<\/i>.<\/p>\n<p>The easiest way to marshal an object&#8217;s interface is to ask somebody else to manage it for you: The <code>Ro\u00adGet\u00adAgile\u00adReference<\/code> function creates a new object that represents an <i>agile reference<\/i> to the original object. In COM, the term <i>agile<\/i> means that it can be used in any apartment. You can then ask that agile reference to <i>resolve<\/i> a reference to the original interface, and it will give you an object which you can use from the apartment doing the resolving.<\/p>\n<p><b>Bonus reading<\/b>: <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20191202-00\/?p=103171\"> When should I use delayed-marshaling when creating an agile reference<\/a>?<\/p>\n<p>A lower-level method is to use <code>Co\u00adMarshal\u00adInter\u00adThread\u00adInterface\u00adIn\u00adStream<\/code> to take an object interface and save it into a byte stream. That stream is a magic cookie that can be used to recover the original interface from any apartment. And since it&#8217;s a stream of bytes, you have any number of ways of sharing those bytes with another thread: You could save them in a global variable, you could write them to a named pipe, or you could print them on a piece of paper, bury it in the ground, then come back and dig up the paper and OCR the digits. Whatever the mechanism, you can pass the bytes to <code>Co\u00adUnmarshal\u00adInterface<\/code> (or its own helper function <code>Co\u00adGet\u00adInterface\u00adAnd\u00adRelease\u00adStream<\/code>) and it will produce an object that you can use.<\/p>\n<p>But we&#8217;re going to look at what happens at an even lower level: The <code>Co\u00adMarshal\u00adInterface<\/code> function is the one that generates the stream. In addition to the obvious parameters (the stream to which to write the bytes, the interface being marshaled, and an interface pointer), there are two somewhat more mysterious parameters: The destination context and the marshal flags.<\/p>\n<p>The destination context describes <i>where<\/i> you intend to unmarshal the object. Here are the destination contexts in order of distance from the source:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Flag<\/th>\n<th>Meaning<\/th>\n<th>Group<\/th>\n<\/tr>\n<tr>\n<td><code>MSHCTX_<wbr \/>CROSSCTX<\/code><\/td>\n<td>Another context in the same apartment.<\/td>\n<td rowspan=\"2\">Same-process<\/td>\n<\/tr>\n<tr>\n<td><code>MSHCTX_<wbr \/>INPROC<\/code><\/td>\n<td>Another apartment in the same process.<\/td>\n<\/tr>\n<tr>\n<td><code>MSHCTX_<wbr \/>LOCAL<\/code><\/td>\n<td>Another process on the same computer<br \/>\nwhich can share memory with the source.<\/td>\n<td rowspan=\"2\">Same-machine<\/td>\n<\/tr>\n<tr>\n<td><code>MSHCTX_<wbr \/>NOSHAREDMEM<\/code><\/td>\n<td>Another process on the same computer<br \/>\nwhich cannot share memory with the source.<\/td>\n<\/tr>\n<tr>\n<td><code>MSHCTX_<wbr \/>DIFFERENT\u00adMACHINE<\/code><\/td>\n<td>Another computer.<\/td>\n<td rowspan=\"2\">Cross-machine<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Marshaling across integrity levels would be a case where the source and destination processes cannot share memory.<\/p>\n<p>Although there are five different marshaling contexts, most marshaling code cares only about which group they belong to: The same-process group (<code>CROSSCTX<\/code> and <code>INPROC<\/code>) the same-machine group (<code>LOCAL<\/code> and <code>NOSHAREDMEM<\/code>) and the cross-machine group (<code>DIFFERENT\u00adMACHINE<\/code>).<\/p>\n<p>Meanwhile, the marshal flags describe <i>how<\/i> you intend to unmarshal the object.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Flag<\/th>\n<th>Number of times to unmarshal<\/th>\n<th>Strong or weak reference<\/th>\n<\/tr>\n<tr>\n<td><code>MSHLFLAGS_<wbr \/>NORMAL<\/code><\/td>\n<td>Exactly once.<\/td>\n<td>Strong<\/td>\n<\/tr>\n<tr>\n<td><code>MSHLFLAGS_<wbr \/>TABLESTRONG<\/code><\/td>\n<td>Any number of times (possibly zero).<\/td>\n<td>Strong<\/td>\n<\/tr>\n<tr>\n<td><code>MSHLFLAGS_<wbr \/>TABLEWEAK<\/code><\/td>\n<td>Any number of times (possibly zero).<\/td>\n<td>Weak<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first case is called &#8220;normal&#8221; because it is the most common case of marshaling: You have a single reference that you want to transfer to another apartment. We&#8217;ll see that knowing in advance that this is how you intend to marshal the object interface allows for some optimizations.<\/p>\n<p>The last two cases are for where the object can be unmarshaled any number of times (possibly zero). They differ in whether the stream itself keeps the object alive.<\/p>\n<p>The marshal flags control the usage pattern for managing the stream.<\/p>\n<p>If you choose either of the &#8220;table&#8221; (reusable) marshaling flags, the sequence is<\/p>\n<ul>\n<li>Call <code>Co\u00adMarshal\u00adInterface<\/code> to write the bytes to the stream.<\/li>\n<li>Call <code>Co\u00adUnmarshal\u00adInterface<\/code> to produce an object from the stream. Repeat this as many times as you like, or skip it entirely.<\/li>\n<li>Call <code>Co\u00adRelease\u00adMarshal\u00adData<\/code> to signal that you are not going to be unmarshaling from the stream any more.<\/li>\n<\/ul>\n<p>The difference between the two &#8220;table&#8221; versions is whether the stream itself keeps the object alive. If you choose a weak reference, then it is your responsibility not to call <code>Co\u00adUnmarshal\u00adInterface<\/code> once the object has been destroyed. (Typically, you accomplish this by ensuring that the stream&#8217;s lifetime is encompassed by the object&#8217;s lifetime.)<\/p>\n<p>If you choose &#8220;normal&#8221; (one-time) marshaling, the sequence is<\/p>\n<ul>\n<li>Call <code>Co\u00adMarshal\u00adInterface<\/code> to write the bytes to the stream.<\/li>\n<li>Either\n<ul>\n<li>Call <code>Co\u00adUnmarshal\u00adInterface<\/code> to produce an object from the stream, or<\/li>\n<li>Call <code>Co\u00adRelease\u00adMarshal\u00adData<\/code> to abandon the operation.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>In the case of &#8220;normal&#8221; marshaling, once you call <code>Co\u00adUnmarshal\u00adInterface<\/code> or <code>Co\u00adRelease\u00adMarshal\u00adData<\/code>, the stream can no longer be used further. Conceptually, you can imagine that calling <code>Co\u00adUnmarshal\u00adInterface<\/code> &#8220;normal&#8221; marshaling is like &#8220;table strong&#8221; marshaling, with the added feature that the <code>Co\u00adUnmarshal\u00adInterface<\/code> implicitly performs a <code>Co\u00adRelease\u00adMarshal\u00adData<\/code> when it&#8217;s done.<\/p>\n<p>Next time, we&#8217;ll start looking at the mechanics of how COM marshaling is performed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The outermost simple layer, and the more complex inner layer.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-106750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The outermost simple layer, and the more complex inner layer.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106750","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=106750"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106750\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=106750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}