{"id":44033,"date":"2014-09-18T07:00:00","date_gmt":"2014-09-18T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/09\/18\/the-stream-pointer-position-in-idataobjectgetdata-and-idataobjectgetdatahere-is-significant\/"},"modified":"2014-09-18T07:00:00","modified_gmt":"2014-09-18T07:00:00","slug":"the-stream-pointer-position-in-idataobjectgetdata-and-idataobjectgetdatahere-is-significant","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140918-00\/?p=44033","title":{"rendered":"The stream pointer position in IDataObject::GetData and IDataObject::GetDataHere is significant"},"content":{"rendered":"<p>\nAn oft-overlooked detail of the\n<code>IData&shy;Object::Get&shy;Data<\/code> and\n<code>IData&shy;Object::Get&shy;Data&shy;Here<\/code> methods\nis the position of the stream pointer when the result is a stream.\nThese rules are\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/ms687266\">\nburied in the documentation<\/a>,\nso I&#8217;m going to call them out louder.\n<\/p>\n<p>\nLet&#8217;s look at\n<code>IData&shy;Object::Get&shy;Data<\/code> first.\n<\/p>\n<p>\nIf\n<code>IData&shy;Object::Get&shy;Data<\/code>\nreturns a stream,\nthen the stream pointer must be positioned at the\n<i>end<\/i> of the stream before the stream is returned.\nIn other words, the last thing you do before returning\nthe stream is seek it to the end.\nThe contents of the data object are assumed to extend from the\nstart of the stream to the stream&#8217;s position as returned by\n<code>IData&shy;Object::Get&shy;Data<\/code>.\n(And no, I don&#8217;t know why this rule exists.)\n<\/p>\n<p>\nI messed this up in\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2008\/03\/19\/8080215.aspx\">\nmy demonstration of how to drag a stream<\/a>.\nLet&#8217;s fix it.\n<\/p>\n<pre>\n  case DATA_FILECONTENTS:\n    pmed-&gt;tymed = TYMED_ISTREAM;\n    pmed-&gt;pstm = SHOpenRegStream(HKEY_LOCAL_MACHINE,\n       TEXT(\"Hardware\\\\Description\\\\System\\\\CentralProcessor\\\\0\"),\n       TEXT(\"~MHz\"), STGM_READ);\n    <font COLOR=\"blue\">if (pmed-&gt;pstm) {\n      LARGE_INTEGER liZero = { 0, 0 };\n      pmed-&gt;pstm-&gt;Seek(liZero, STREAM_SEEK_END, NULL);\n    }<\/font>\n    return pmed-&gt;pstm ? S_OK : E_FAIL;\n  }\n<\/pre>\n<p>\nBut what if you don&#8217;t know the stream size?\nFor example, what if the stream is coming from a live download?\nWhat if the stream doesn&#8217;t support seeking?\nWhat if the stream is infinite?\nIn those cases, you don&#8217;t really have a choice.\nYou just leave the stream pointer at the beginning and hope for the best.\n(Fortunately, at least in the case of virtual file content,\nthe shell is okay with people who leave the stream pointer at the start\nof the stream.\nProbably for reasons like this.)\n<\/p>\n<p>\nThere is a similar detail with\n<code>IData&shy;Object::Get&shy;Data&shy;Here<\/code>:\nIf you are asked to produce the data into an existing stream,\nyou should write the data starting at the stream&#8217;s current position\nand leave the stream pointer at the end of the data you just wrote.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An oft-overlooked detail of the IData&shy;Object::Get&shy;Data and IData&shy;Object::Get&shy;Data&shy;Here methods is the position of the stream pointer when the result is a stream. These rules are buried in the documentation, so I&#8217;m going to call them out louder. Let&#8217;s look at IData&shy;Object::Get&shy;Data first. If IData&shy;Object::Get&shy;Data returns a stream, then the stream pointer must be positioned at [&hellip;]<\/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-44033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>An oft-overlooked detail of the IData&shy;Object::Get&shy;Data and IData&shy;Object::Get&shy;Data&shy;Here methods is the position of the stream pointer when the result is a stream. These rules are buried in the documentation, so I&#8217;m going to call them out louder. Let&#8217;s look at IData&shy;Object::Get&shy;Data first. If IData&shy;Object::Get&shy;Data returns a stream, then the stream pointer must be positioned at [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44033","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=44033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/44033\/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=44033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=44033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=44033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}