{"id":7963,"date":"2012-03-30T07:00:00","date_gmt":"2012-03-30T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/03\/30\/how-do-i-perform-shell-file-operations-while-avoiding-shell-copy-hooks\/"},"modified":"2012-03-30T07:00:00","modified_gmt":"2012-03-30T07:00:00","slug":"how-do-i-perform-shell-file-operations-while-avoiding-shell-copy-hooks","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120330-00\/?p=7963","title":{"rendered":"How do I perform shell file operations while avoiding shell copy hooks?"},"content":{"rendered":"<p>\nOkay, the subject line of the article gives away the answer\nto the puzzle,\nbut here&#8217;s the puzzle anyway:\nA customer reported a problem with the\n<code>SHFile&shy;Operation<\/code> function:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nConsider the following program:\n<\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;shellapi.h&gt;\nint main()\n{\nSHFILEOPSTRUCT fileStruct = {};\n    fileStruct.wFunc = FO_RENAME;\n    fileStruct.pFrom = L\"C:\\\\a\\0\";\n    fileStruct.pTo   = L\"C:\\\\b\\0\";\n    fileStruct.fFlags= FOF_NO_UI;\n    ::SHFileOperation(&amp;fileStruct);\n    return 0;\n}\n<\/pre>\n<p>\nIf &#8220;a&#8221; is a file, then everything works fine,\nbut if it&#8217;s a directory, then Application Verifier raises\nthe following error:\n<\/p>\n<blockquote><p>\nHeap violation detected<br \/>\nMemory access operation in the context of a freed block: reuse-after-delete or double-delete\n<\/p><\/blockquote>\n<p>\nCan you help explain what we&#8217;re doing wrong?\nSo far as we can tell, all our parameters are correct.\n<\/p>\n<\/blockquote>\n<p>\nThis is one of those &#8220;It doesn&#8217;t work on my machine&#8221; issues,\nbecause the provided sample program runs fine on a freshly-installed\ncopy of Windows.\nWe asked the customer to send us a crash dump file,\nand from that crash dump the source of the problem was obvious:\n<\/p>\n<pre>\neax=00000001 ebx=00000000 ecx=73d34c58 edx=00270001 esi=09fa2ff8 edi=00000000\neip=10001131 esp=0026dea8 ebp=0026df24 iopl=0         nv up ei pl nz na po nc\ncs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010200\nContoso+0x1131:\n10001131 8b4604          mov     eax,dword ptr [esi+4] ds:002b:09fa2ffc=????????\n0:000&gt; k\n  *** Stack trace for last set context - .thread\/.cxr resets it\nChildEBP RetAddr\nWARNING: Stack unwind information not available. Following frames may be wrong.\n0026df24 75a3554a Contoso+0x1131\n0026df64 75a1b07c ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108\n0026dfb8 75a1aff1 ole32!CApartmentActivator::CreateInstance+0x112\n0026dfd8 75a1ae16 ole32!CProcessActivator::CCICallback+0x6d\n0026dff8 75a1adc7 ole32!CProcessActivator::AttemptActivation+0x2c\n0026e034 75a1b0df ole32!CProcessActivator::ActivateByContext+0x4f\n0026e05c 75a3554a ole32!CProcessActivator::CreateInstance+0x49\n0026e09c 75a352ce ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108\n0026e2fc 75a3554a ole32!CClientContextActivator::CreateInstance+0xb0\n0026e33c 75a35472 ole32!ActivationPropertiesIn::DelegateCreateInstance+0x108\n0026eb18 75a45916 ole32!ICoCreateInstanceEx+0x404\n0026eb78 75a45877 ole32!CComActivator::DoCreateInstance+0xd9\n0026eb9c 75a45830 ole32!CoCreateInstanceEx+0x38\n0026ebcc 75c61fe0 ole32!CoCreateInstance+0x37\n0026ee64 75c61354 shell32!_SHCoCreateInstance+0x1ac\n0026ee88 75c1b904 shell32!SHExtCoCreateInstance+0x1e\n0026eec8 75becbcf shell32!SHExtCoCreateInstanceString+0x43\n0026f10c 75beca76 shell32!CreateCopyHooks+0xe1\n0026f344 75bec9da shell32!CallCopyHooks+0x4b\n0026f370 75bec95b shell32!CallFileCopyHooks+0x29\n0026f5bc 75bec8a4 shell32!CFileOperation::CopyHooks+0x119\n0026fa3c 75c37955 shell32!CCopyWorkItem::_UpFrontConfirmations+0xb7\n0026fc6c 75c378b0 shell32!CCopyWorkItem::ProcessWorkItem+0x83\n0026fca0 75c37fda shell32!CRecursiveFolderOperation::Do+0x1d5\n0026fce4 75c39a19 shell32!CFileOperation::_EnumRootDo+0x14e\n0026fd4c 75c397b9 shell32!CFileOperation::PrepareAndDoOperations+0x27f\n0026fd74 75c396c7 shell32!SHFileOperationWithAdditionalFlags+0xe9\n<\/pre>\n<p>\nThe crash is in some third party component named Contoso,\nwhich is running because it is being <code>Co&shy;Create<\/code>&#8216;d.\nThe call came from <code>Create&shy;Copy&shy;Hooks<\/code>,\nand it doesn&#8217;t require very much in the way of psychic powers\nto conclude that the shell is creating the Contoso object\nbecause it registered as a copy hook.\n<\/p>\n<p>\nThis also explains why the problem occurs only on the customer&#8217;s\nmachine:\nThe customer installed the Contoso shell extension and we didn&#8217;t.\n<\/p>\n<p>\nOkay, so the problem is that the Contoso shell extension has\na use-after-free memory corruption bug.\n(Some Web searching revealed that a lot of people had encountered\nproblems with the Contoso shell extension.)\n<\/p>\n<p>\nThe <code>FOFX_NO&shy;COPY&shy;HOOKS<\/code> flag comes in handy here.\nSetting this extended flag disables copy hooks for your file operation.\nExtended flags cannot be passed to the classic\n<code>SHFileOperation<\/code> function because the\n<code>SHFILEOPSTRUCT<\/code> structure uses a 16-bit <code>WORD<\/code>\nfor the <code>fFlags<\/code> member,\nbut the\n<code>FOFX_NO&shy;COPY&shy;HOOKS<\/code> flag has the numerical\nvalue <code>0x00800000<\/code> which doesn&#8217;t fit in a 16-bit integer.\n(The &#8220;X&#8221; at the end of the prefix is another clue.)\nThe way to set extended flags is to use the\n<code>IFileOperation<\/code> interface.\n<\/p>\n<pre>\n\/\/ Just for fun, I'll use ATL templates instead of raw C++.\nHRESULT RenameAtoB()\n{\n HRESULT hr;\n <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/05\/20\/135841.aspx\">CCoInitialize<\/a> init;\n hr = init;\n if (FAILED(hr)) return hr;\n CComPtr&lt;IFileOperation&gt; spfo;\n hr = spfo.CoCreateInstance(CLSID_FileOperation);\n if (FAILED(hr)) return hr;\n hr = spfo-&gt;SetOperationFlags(FOFX_NOCOPYHOOKS);\n if (FAILED(hr)) return hr;\n CComPtr&lt;IShellItem&gt; spsi;\n hr = SHCreateItemFromParsingName(L\"C:\\\\a\", NULL,\n                           IID_PPV_ARGS(&amp;spsi));\n if (FAILED(hr)) return hr;\n hr = spfo-&gt;RenameItem(spsi, L\"b\", NULL);\n if (FAILED(hr)) return hr;\n hr = spfo-&gt;PerformOperations();\n if (FAILED(hr)) return hr;\n return S_OK;\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Okay, the subject line of the article gives away the answer to the puzzle, but here&#8217;s the puzzle anyway: A customer reported a problem with the SHFile&shy;Operation function: Consider the following program: #include &lt;windows.h&gt; #include &lt;shellapi.h&gt; int main() { SHFILEOPSTRUCT fileStruct = {}; fileStruct.wFunc = FO_RENAME; fileStruct.pFrom = L&#8221;C:\\\\a\\0&#8243;; fileStruct.pTo = L&#8221;C:\\\\b\\0&#8243;; fileStruct.fFlags= FOF_NO_UI; ::SHFileOperation(&amp;fileStruct); [&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-7963","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Okay, the subject line of the article gives away the answer to the puzzle, but here&#8217;s the puzzle anyway: A customer reported a problem with the SHFile&shy;Operation function: Consider the following program: #include &lt;windows.h&gt; #include &lt;shellapi.h&gt; int main() { SHFILEOPSTRUCT fileStruct = {}; fileStruct.wFunc = FO_RENAME; fileStruct.pFrom = L&#8221;C:\\\\a\\0&#8243;; fileStruct.pTo = L&#8221;C:\\\\b\\0&#8243;; fileStruct.fFlags= FOF_NO_UI; ::SHFileOperation(&amp;fileStruct); [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7963","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=7963"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7963\/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=7963"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=7963"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=7963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}