{"id":97625,"date":"2017-12-21T07:00:00","date_gmt":"2017-12-21T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=97625"},"modified":"2019-03-13T01:21:18","modified_gmt":"2019-03-13T08:21:18","slug":"20171221-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20171221-00\/?p=97625","title":{"rendered":"What&#8217;s the difference between VARIANT and VARIANTARG?"},"content":{"rendered":"<p>One of my colleagues asked me, &#8220;What&#8217;s the difference between <code>VARIANT<\/code> and <code>VARIANTARG<\/code>?&#8221; <\/p>\n<p>If you look at the definitions in the <code>oaidl.h<\/code> header file, you&#8217;ll see that <code>VARIANTARG<\/code> is just an alias for <code>VARIANT<\/code>. <\/p>\n<pre>\ntypedef VARIANT VARIANTARG;\n\ntypedef VARIANT *LPVARIANTARG;\n<\/pre>\n<p>&#8220;Why have two names for the same thing?&#8221; <\/p>\n<p>The two structures are physically identical, but the rules surrounding them are different. <\/p>\n<p>This is mentioned rather opaquely in <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms221627(v=vs.85).aspx\">the documentation for <code>VARIANT<\/code><\/a>: <\/p>\n<blockquote CLASS=\"q\">\n<p><b>VARIANTARG<\/b> describes arguments passed within DISPPARAMS, and <b>VARIANT<\/b> to specify variant data that cannot be passed by reference. <\/p>\n<p>When a variant refers to another variant by using the VT_VARIANT | VT_BYREF vartype, the variant being referred to cannot also be of type VT_VARIANT | VT_BYREF. VARIANTs can be passed by value, even if VARIANTARGs cannot. <\/p>\n<\/blockquote>\n<p>The first sentence says that you use <code>VARIANTARG<\/code> as part of a <code>DISPPARAMS<\/code>, which is the structure used to pass parameters (also known as &#8220;arguments&#8221;) to methods of dispatch interfaces. <\/p>\n<p>The second sentence is not relevant to the discussion. It says that only one level of pointer chasing is allowed. You can&#8217;t send the method on a wild goose chase where you pass a variant that says &#8220;The real data is over there, in that other variant&#8221;, and then have the second variant say, &#8220;Ha ha, fooled, you. The real data is over there in that other other variant.&#8221; <\/p>\n<p>The third sentence starts to hint at the underlying issue. It says that <code>VARIANT<\/code>s can be passed by value, but <code>VARIANTARG<\/code>s cannot. <\/p>\n<p>Interesting, but no real insight as to why you can pass <code>VARIANT<\/code> by value but not <code>VARIANTARG<\/code>. <\/p>\n<p>There&#8217;s another MSDN page titled <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms891678.aspx\">VARIANT and VARIANTARG<\/a>. Maybe that&#8217;ll help us get to the bottom of the mystery. <\/p>\n<blockquote CLASS=\"q\">\n<p>The <b>VARIANT<\/b> type cannot have the <b>VT_BYREF<\/b> bit set. <\/p>\n<\/blockquote>\n<p>Aha, that&#8217;s the difference. The <code>VARIANTARG<\/code> structure is allowed to say, &#8220;Hey, I don&#8217;t contain the data you want, but you can look over there for it.&#8221; For example, it could set its variant type to <code>VT_BYREF | VT_I4<\/code> to say, &#8220;There is an integer, but it&#8217;s not stored in the <code>lVal<\/code> member. Instead, you have to go to the <code>plVal<\/code> member, which is a pointer to the integer you want.&#8221; <\/p>\n<p>This explains why <code>VARIANT<\/code> can be copied, but <code>VARIANTARG<\/code> cannot: If you try to copy a <code>VARIANTARG<\/code> that uses <code>VT_BYREF<\/code>, you are just copying the raw pointer to the data, not the data itself. You have no control over the memory being pointed to, so you have no way to prevent it from being freed. <\/p>\n<p>Using <code>VT_BYREF<\/code> is allowed in a <code>DISPPARAMS<\/code> because the caller assumes the responsibility of keeping the pointed-to data valid for the duration of the method call. That&#8217;s just one of the <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20060320-13\/?p=31853\">basic ground rules of programming<\/a>, specifically the stability requirement. The caller has to wait for the method call to return before it can free the memory pointed to by the <code>VARIANTARG<\/code>. <\/p>\n<p>Okay, so what if you&#8217;re implementing a method and you want to make a copy of the <code>VARIANTARG<\/code>? How do you deal with the <code>VT_BYREF<\/code>? <\/p>\n<p>This is where <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms221184(v=vs.85).aspx\">the <code>Variant&shy;Copy&shy;Ind<\/code> function<\/a> comes into play. This function takes a <code>VARIANTARG<\/code>, possibly with <code>VT_BYREF<\/code>, and converts it into a <code>VARIANT<\/code>, with all <code>VT_BYREF<\/code> removed. It does this by chasing the pointer one level and copying the value back into the <code>VARIANT<\/code>. For example, if the <code>VARIANTARG<\/code> were a <code>VT_BYREF | VT_I4<\/code>, then the <code>Variant&shy;Copy&shy;Ind<\/code> function would follow the <code>plVal<\/code> pointer, read the integer stored there, and copy it to the output <code>VARIANT<\/code>&#8216;s <code>lVal<\/code> member, resulting in a simple <code>VT_I4<\/code>. <\/p>\n<p>The &#8220;Ind&#8221; therefore stands for &#8220;Indirect&#8221;. The <code>Variant&shy;Copy&shy;Ind<\/code> function indirects through the pointer hiding inside the <code>VT_BYREF<\/code>. <\/p>\n<p>Well, that was a strange bit of spelunking. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Well, is it an argument?<\/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-97625","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Well, is it an argument?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97625","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=97625"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97625\/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=97625"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=97625"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=97625"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}