{"id":24733,"date":"2007-10-19T10:00:00","date_gmt":"2007-10-19T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/10\/19\/other-problems-traced-to-violating-com-single-threaded-apartment-rules-in-the-shell\/"},"modified":"2007-10-19T10:00:00","modified_gmt":"2007-10-19T10:00:00","slug":"other-problems-traced-to-violating-com-single-threaded-apartment-rules-in-the-shell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20071019-00\/?p=24733\/","title":{"rendered":"Other problems traced to violating COM single-threaded apartment rules in the shell"},"content":{"rendered":"<p>\nProbably the biggest category of problems that can be traced to\nviolating COM single-threaded apartment rules in the shell is\nusing an object from the wrong thread.\nOf course, nobody admits to doing this up front,\nThey just report that the shell is broken.\n<\/p>\n<blockquote CLASS=\"q\"><p>\nWe can&#8217;t enumerate the items on the desktop any more.\nWe take the pointer returned by <code>SHGetDesktopFolder<\/code>\nand call <code>IShellFolder::EnumObjects<\/code>, but no objects\ncome out.\nThis code used to work on Windows&nbsp;XP.\n<\/p><\/blockquote>\n<p>\nThere isn&#8217;t enough information to diagnose the problem,\nand if you just do what they claim doesn&#8217;t work,\nyou find that it works:\n<\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;ole2.h&gt;\n#include &lt;shlobj.h&gt;\n#include &lt;shlwapi.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;tchar.h&gt;\nINT __cdecl\n_tmain(\n    INT iArgc,\n    __in_ecount(iArgc) PTSTR ppszArgv[]\n    )\n{\n if (SUCCEEDED(CoInitialize(NULL))) {\n  IShellFolder *psf;\n  if (SUCCEEDED(SHGetDesktopFolder(&amp;psf))) {\n   IEnumIDList *peidl;\n   if (SUCCEEDED(psf-&gt;EnumObjects(NULL, SHCONTF_FOLDERS |\n                         SHCONTF_NONFOLDERS, &amp;peidl)) &amp;&amp; peidl) {\n    LPITEMIDLIST pidl;\n    while (peidl-&gt;Next(1, &amp;pidl, NULL) == S_OK) {\n     STRRET str;\n     if (SUCCEEDED(psf-&gt;GetDisplayNameOf(pidl,\n                                         SHGDN_NORMAL, &amp;str))) {\n      TCHAR sz[MAX_PATH];\n      if (SUCCEEDED(StrRetToBuf(&amp;str, pidl, sz, MAX_PATH))) {\n       _tprintf(TEXT(\"%s\\n\"), sz);\n      }\n     }\n     ILFree(pidl);\n    }\n   }\n   psf-&gt;Release();\n  }\n  CoUninitialize();\n }\n return 0;\n}\n<\/pre>\n<p>\nWhen given this simple program that does what they claim doesn&#8217;t work,\nthe customer explained that they cache the desktop folder.\nIt works for a while, and then stops working.\nThe code is complicated, so they haven&#8217;t been able to isolate the problem yet.\nThey did find that if they didn&#8217;t cache the pointer\nand just called <code>SHGetDesktopFolder<\/code> each time they needed it,\nthen they didn&#8217;t have the problem.\n<\/p>\n<p>\nI never got a confirmation,\nbut I&#8217;m pretty sure that they are violating COM apartment threading\nmodel rules and obtaining the desktop folder obtained on one thread,\nthen using it on another.\nApartment model rules specify that you must use an object on the same\nthread that created it.\nIf you want to use it on another thread,\nyou have to use a helper function like\n<code>CoMarshalInterThreadInterfaceInStream<\/code>.\nIf you just dive in and use it on another thread\n(known informally as\n&#8220;<a HREF=\"http:\/\/blogs.msdn.com\/tonyschr\/archive\/2006\/12\/11\/interface-smuggling.aspx\">smuggling<\/a>&#8220;),\nthen all sorts of strange things happen.\nIn this case, the folder can&#8217;t enumerate objects any more.\n<\/p>\n<p>\nMoral of the story:\nStick to the rules for COM objects.\nIf you don&#8217;t, you may get away with it for a little while,\nbut someday your sins may catch up to you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Probably the biggest category of problems that can be traced to violating COM single-threaded apartment rules in the shell is using an object from the wrong thread. Of course, nobody admits to doing this up front, They just report that the shell is broken. We can&#8217;t enumerate the items on the desktop any more. We [&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-24733","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Probably the biggest category of problems that can be traced to violating COM single-threaded apartment rules in the shell is using an object from the wrong thread. Of course, nobody admits to doing this up front, They just report that the shell is broken. We can&#8217;t enumerate the items on the desktop any more. We [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24733","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=24733"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24733\/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=24733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=24733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=24733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}