{"id":7923,"date":"2012-04-05T07:00:00","date_gmt":"2012-04-05T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/04\/05\/you-can-use-an-overlapped-structure-with-synchronous-io-too\/"},"modified":"2012-04-05T07:00:00","modified_gmt":"2012-04-05T07:00:00","slug":"you-can-use-an-overlapped-structure-with-synchronous-io-too","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120405-00\/?p=7923","title":{"rendered":"You can use an OVERLAPPED structure with synchronous I\/O, too"},"content":{"rendered":"<p>\nEven if you didn&#8217;t open a file with\n<code>FILE_FLAG_OVERLAPPED<\/code>,\nyou can still use the <code>OVERLAPPED<\/code> structure\nwhen you issue reads and writes.\nMind you,\nthe I\/O will still complete synchronously,\nbut you can take advantage of the other stuff\nthat <code>OVERLAPPED<\/code> has to offer.\n<\/p>\n<p>\nSpecifically, you can take advantage of the\n<code>Offset<\/code> and <code>OffsetHigh<\/code> members\nto issue the I\/O against a file location different from\nthe current file pointer.\n(This is a file pointer in the sense of\n<code>Set&shy;File&shy;Pointer<\/code>\nand not in the sense of the C runtime <code>FILE*<\/code>.)\nIf your program does a lot of reads and writes to random locations\nin a file, using the synchronous <code>OVERLAPPED<\/code>\nstructure saves you a call to\n<code>Set&shy;File&shy;Pointer<\/code> at each I\/O.\n<\/p>\n<p>\nLet&#8217;s illustrate this by writing some code to walk through\na file format that contains a lot of offsets to other\nparts of the file:\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2010\/10\/18\/10077133.aspx\">\nThe ICO file format<\/a>.\nFirst, the old-fashioned way:\n<\/p>\n<pre>\n#define <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/02\/12\/71851.aspx\">UNICODE<\/a>\n#define _UNICODE\n#include &lt;windows.h&gt;\n#include &lt;pshpack1.h&gt;\nstruct ICONDIRHEADER {\n    WORD idReserved;\n    WORD idType;\n    WORD idCount;\n};\nstruct ICONDIRENTRY {\n    BYTE bWidth;\n    BYTE bHeight;\n    BYTE bColorCount;\n    BYTE  bReserved;\n    WORD  wPlanes;\n    WORD  wBitCount;\n    DWORD dwBytesInRes;\n    DWORD dwImageOffset;\n};\n#include &lt;poppack.h&gt;\nBOOL ReadBufferAt(__in HANDLE hFile,\n    __out_bcount(cbBuffer) void *pvBuffer,\n    DWORD cbBuffer,\n    DWORD64 offset)\n{\n LARGE_INTEGER li;\n DWORD cbRead;\n li.QuadPart = offset;\n return SetFilePointerEx(hFile, li, nullptr, FILE_BEGIN) &amp;&amp;\n        ReadFile(hFile, pvBuffer, cbBuffer, &amp;cbRead, nullptr) &amp;&amp;\n        cbBuffer == cbRead;\n}\nint __cdecl wmain(int argc, wchar_t **argv)\n{\n HANDLE hFile = CreateFile(argv[1], GENERIC_READ,\n  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n  nullptr, OPEN_EXISTING, 0, nullptr);\n if (hFile != INVALID_HANDLE_VALUE) {\n  ICONDIRHEADER hdr;\n  if (ReadBufferAt(hFile, &amp;hdr, sizeof(hdr), 0) &amp;&amp;\n      hdr.idReserved == 0 &amp;&amp; hdr.idType == 1) {\n   for (UINT uiIcon = 0; uiIcon &lt; hdr.idCount; uiIcon++) {\n    ICONDIRENTRY entry;\n    if (ReadBufferAt(hFile, &amp;entry, sizeof(entry),\n                     sizeof(hdr) + uiIcon * sizeof(entry))) {\n     void *pvData = LocalAlloc(LMEM_FIXED, entry.dwBytesInRes);\n     if (pvData) {\n      if (ReadBufferAt(hFile, pvData,\n                       entry.dwBytesInRes, entry.dwImageOffset)) {\n       \/\/ process one image in the icon\n      }\n      LocalFree(pvData);\n     }\n    }\n   }\n  }\n  CloseHandle(hFile);\n }\n return 0;\n}\n<\/pre>\n<p>\nRun this program with the name of an icon file on the command line,\nand nothing interesting happens because the program doesn&#8217;t\ngenerate any output.\nBut if you step through it, you can see that we start by\nreading the <code>ICON&shy;DIR&shy;HEADER<\/code>\nto verify that it&#8217;s an icon and determine the number of images.\nWe then loop through the images: For each one,\nwe read the <code>ICON&shy;DIR&shy;ENTRY<\/code>\n(specifying the explicit file offset),\nthen read the image data (again, specifying the explicit\nfile offset).\n<\/p>\n<p>\nWe use the <code>Read&shy;Buffer&shy;At<\/code> function\nto read data from the file.\nFor each read, we first call <code>Set&shy;File&shy;Pointer<\/code>\nto position the file pointer at the byte we want to read,\nthen call <code>Read&shy;File<\/code> to read it.\n<\/p>\n<p>\nLet&#8217;s change this program to take advantage of our newfound knowledge:\n<\/p>\n<pre>\nBOOL ReadBufferAt(__in HANDLE hFile,\n    __out_bcount(cbBuffer) void *pvBuffer,\n    DWORD cbBuffer,\n    DWORD64 offset)\n{\n OVERLAPPED o = { 0 };\n o.Offset = static_cast&lt;DWORD&gt;(offset);\n o.OffsetHigh = static_cast&lt;DWORD&gt;(offset &gt;&gt; 32);\n DWORD cbRead;\n return ReadFile(hFile, pvBuffer, cbBuffer, &amp;cbRead, &amp;o) &amp;&amp;\n        cbBuffer == cbRead;\n}\n<\/pre>\n<p>\nWe merge the\n<code>Set&shy;File&shy;Pointer<\/code> call into the\n<code>Read&shy;File<\/code> by specifying the desired byte\noffset in the optional <code>OVERLAPPED<\/code> structure.\nThe I\/O will still complete synchronously\n(since we opened the handle synchronously),\nbut we saved ourselves the hassle of having to call\ntwo functions when it could be done with just one.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Even if you didn&#8217;t open a file with FILE_FLAG_OVERLAPPED, you can still use the OVERLAPPED structure when you issue reads and writes. Mind you, the I\/O will still complete synchronously, but you can take advantage of the other stuff that OVERLAPPED has to offer. Specifically, you can take advantage of the Offset and OffsetHigh members [&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-7923","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Even if you didn&#8217;t open a file with FILE_FLAG_OVERLAPPED, you can still use the OVERLAPPED structure when you issue reads and writes. Mind you, the I\/O will still complete synchronously, but you can take advantage of the other stuff that OVERLAPPED has to offer. Specifically, you can take advantage of the Offset and OffsetHigh members [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7923","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=7923"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7923\/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=7923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=7923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=7923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}