{"id":40873,"date":"2004-01-27T07:00:00","date_gmt":"2004-01-27T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/01\/27\/some-reasons-not-to-do-anything-scary-in-your-dllmain\/"},"modified":"2004-01-27T07:00:00","modified_gmt":"2004-01-27T07:00:00","slug":"some-reasons-not-to-do-anything-scary-in-your-dllmain","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040127-00\/?p=40873","title":{"rendered":"Some reasons not to do anything scary in your DllMain"},"content":{"rendered":"<p>As everybody knows by now,\nyou&#8217;re not supposed to do anything even remotely\ninteresting in your\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/dllmain.asp\">\nDllMain<\/a> function.\n<a HREF=\"\/oleglv\/\" \/>Oleg Lvovitch<\/a> has written two very good\narticles about this,\n<a HREF=\"http:\/\/weblogs.asp.net\/oleglv\/archive\/2003\/12\/12\/43068.aspx\">\none about how things work<\/a>,\nand\n<a HREF=\"http:\/\/weblogs.asp.net\/oleglv\/archive\/2003\/12\/12\/43069.aspx\">\none about what goes wrong when they don&#8217;t work<\/a>.<\/p>\n<p>\nHere&#8217;s another reason not to do anything remotely interesting\nin your DllMain:  It&#8217;s common to load a library without actual\nintent to invoke its full functionality. For example, somebody\nmight load your library like this:\n<\/p>\n<pre>\n\/\/ error checking deleted for expository purposes\nhinst = LoadLibrary(you);\nhicon = LoadIcon(you, MAKEINTRESOURCE(5));\nFreeLibrary(hinst);\n<\/pre>\n<p>\nThis code just wants your icon.\nIt would be very surprised (and perhaps even upset) if\nyour DLL did something heavy like starting up a\ntimer or a thread.\n<\/p>\n<p>\n(Yes, this could be avoided by using\nLoadLibraryEx and LOAD_LIBRARY_AS_DATAFILE, but\nthat&#8217;s not my point.)\n<\/p>\n<p>\nAnother case where your library gets loaded even though no\ncode is going to be run is when it gets tugged along as\na dependency for some other DLL. Suppose &#8220;middle&#8221; is the name\nof some intermediate DLL that is linked to your DLL.<\/p>\n<pre>\nhinst = LoadLibrary(middle);\npfn = GetProcAddress(hinst, \"SomeFunction\");\npfn(...);\nFreeLibrary(hinst);\n<\/pre>\n<p>\nWhen &#8220;middle&#8221; is loaded, your DLL will get loaded and\ninitialized, too.  So your initialization runs\neven if &#8220;SomeFunction&#8221; doesn&#8217;t use your DLL.\n<\/p>\n<p>\nThis &#8220;intermediate DLL loaded for a brief time&#8221; scenario\nis actually quite common.\nFor example, if somebody does &#8220;Regsvr32 middle.dll&#8221;,\nthat will load the middle DLL to call its DllRegisterServer\nfunction, which typically doesn&#8217;t do much other than\ninstall some registry keys. It almost certainly doesn&#8217;t\ncall into your helper DLL.\n<\/p>\n<p>\nAnother example is the opening of the Control Panel folder.\nThe Control Panel folder loads every *.cpl file so it\ncan call its\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/cplapplet.asp\">CplApplet<\/a>\nfunction to determine what icon to display.\nAgain, this typically will not call into your helper DLL.\n<\/p>\n<p>\nAnd under no circumstances should you create any objects\nwith thread affinity in your DLL_PROCESS_ATTACH handler.\nYou have no control over which thread will send the\nDLL_PROCESS_ATTACH message, nor which thread will send\nthe DLL_PROCESS_DETACH message. The thread that sends the\nDLL_PROCESS_ATTACH message might terminate immediately\nafter it loads your DLL. Any object with thread-affinity\nwill then stop working since its owner thread is gone.\n<\/p>\n<p>\nAnd even if that thread survives, there is no guarantee\nthat the thread that calls FreeLibrary is the same one\nthat called LoadLibrary. So you can&#8217;t clean up those\nobjects with thread affinity in DLL_PROCESS_DETACH since\nyou&#8217;re on the wrong thread.\n<\/p>\n<p>\nAnd absolutely under no circumstances should you be doing\nanything as crazy as creating a window inside your\nDLL_PROCESS_ATTACH.\nIn addition to the thread affinity issues, there&#8217;s the\nproblem of global hooks. Hooks running inside the loader\nlock are a recipe for disaster. Don&#8217;t be surprised if\nyour machine deadlocks.\n<\/p>\n<p>Even more examples to come tomorrow.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As everybody knows by now, you&#8217;re not supposed to do anything even remotely interesting in your DllMain function. Oleg Lvovitch has written two very good articles about this, one about how things work, and one about what goes wrong when they don&#8217;t work. Here&#8217;s another reason not to do anything remotely interesting in your DllMain: [&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-40873","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>As everybody knows by now, you&#8217;re not supposed to do anything even remotely interesting in your DllMain function. Oleg Lvovitch has written two very good articles about this, one about how things work, and one about what goes wrong when they don&#8217;t work. Here&#8217;s another reason not to do anything remotely interesting in your DllMain: [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/40873","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=40873"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/40873\/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=40873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=40873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=40873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}