{"id":45221,"date":"2015-07-03T07:00:00","date_gmt":"2015-07-03T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150703-00\/?p=45221\/"},"modified":"2019-03-13T12:17:00","modified_gmt":"2019-03-13T19:17:00","slug":"20150703-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150703-00\/?p=45221","title":{"rendered":"Why does the BackupWrite function take a pointer to a modifiable buffer when it shouldn&#8217;t be modifying the buffer?"},"content":{"rendered":"<p>The <a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa362511(v=vs.85).aspx\"><code>Backup&shy;Write<\/code><\/a> function takes a non-const pointer to the buffer to be written to the file being restored. Will it actually modify the buffer? Assuming it doesn&#8217;t, why wasn&#8217;t it declared const? It would be much more convenient if it took a const pointer to the buffer, so that people with const buffers didn&#8217;t have to <code>const_cast<\/code> every time they called the function. Would changing the parameter from non-const to const create any compatibility problems? <\/p>\n<p>Okay, let&#8217;s take the questions in order. <\/p>\n<p>Will it actually modify the buffer? No. <\/p>\n<p>Why wasn&#8217;t it declared const? My colleague <a HREF=\"http:\/\/blogs.msdn.com\/b\/aaron_margosis\/\">Aaron Margosis<\/a> explained that the function dates back to Windows NT 3.1, when const-correctness was rarely considered. A lot of functions from that area (particularly in the kernel) suffer from the same problem. For example, the computer name passed to the <code>Reg&shy;Connect&shy;Registry<\/code> function is a non-const pointer even though the function never writes to it. <\/p>\n<p>Last question: Can the parameter be changed from non-const to const without breaking compatibility? <\/p>\n<p>It would not cause problems from a binary compatibility standpoint, because a const pointer and a non-const pointer take the same physical form in Win32. However, it breaks source code compatiblity. Consider the following code fragment: <\/p>\n<pre>\nBOOL WINAPI TestModeBackupWrite(\n  HANDLE hFile,\n  LPBYTE lpBuffer,\n  DWORD nNumberOfBytesToWrite,\n  LPDWORD lpNumberOfBytesWritten,\n  BOOL bAbort,\n  BOOL bProcessSecurity,\n  LPVOID *lpContext)\n{\n ... simulate a BackupWrite ...\n return TRUE;\n}\n\nBOOL (WINAPI *BACKUPWRITEPROC)(HANDLE, LPBYTE, DWORD,\n                 LPDWORD, BOOL, BOOL, LPVOID *);\nBACKUPWRITEPROC TestableBackupWrite;\n\nvoid SetTestMode(bool testing)\n{\n if (testing) {\n  TestableBackupWrite = TestModeBackupWrite;\n } else {\n  TestableBackupWrite = BackupWrite;\n }\n}\n\n<\/pre>\n<p>The idea here is that the program can be run in test mode, say to do a simulated restore. (You see this sort of thing a lot with DVD-burning software.) The program uses <code>Testable&shy;Backup&shy;Write<\/code> whenever it wants to write to a file being restored from backup. In test mode, <code>Testable&shy;Backup&shy;Write<\/code> points to the <code>Test&shy;Mode&shy;Backup&shy;Write<\/code> function; in normal mode, it points to the <code>Backup&shy;Write<\/code> function. <\/p>\n<p>If the second parameter were changed from <code>LPBYTE<\/code> to <code>const BYTE *<\/code>, then the above code would hit a compiler error. <\/p>\n<p>Mind you, maybe it&#8217;s worth breaking some source code in order to get better const-correctness, but for now, the cost\/benefit tradeoff biases toward leaving things alone. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>An artifact of an earlier time.<\/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":[2],"class_list":["post-45221","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>An artifact of an earlier time.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/45221","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=45221"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/45221\/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=45221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=45221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=45221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}