{"id":43833,"date":"2014-10-16T07:00:00","date_gmt":"2014-10-16T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/10\/16\/if-only-dlls-can-get-dllmain-notifications-how-can-an-exe-receive-a-notification-when-a-thread-is-created-for-example\/"},"modified":"2014-10-16T07:00:00","modified_gmt":"2014-10-16T07:00:00","slug":"if-only-dlls-can-get-dllmain-notifications-how-can-an-exe-receive-a-notification-when-a-thread-is-created-for-example","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141016-00\/?p=43833\/","title":{"rendered":"If only DLLs can get DllMain notifications, how can an EXE receive a notification when a thread is created (for example)?"},"content":{"rendered":"<p>\nWhen a DLL is loaded, it receives a\n<code>DLL_PROCESS_ATTACH<\/code> notification,\nand when it is unloaded (or when the process terminates),\nit gets a\n<code>DLL_PROCESS_DETACH<\/code> notification.\nDLLs also receive\n<code>DLL_THREAD_ATTACH<\/code> notifications\nwhen a thread is created and\n<code>DLL_THREAD_DETACH<\/code> notifications\nwhen a thread exits.\nBut what if you are an EXE?\nEXEs don&#8217;t have a <code>Dll&shy;Main<\/code>,\nso there is no way to receive these notifications.\n<\/p>\n<p>\nThe trick here is to hire a lackey.\n<\/p>\n<p>\nCreate a helper DLL, called, say, <code>LACKEY.DLL<\/code>.\nYour EXE links to the lackey,\nand the lackey&#8217;s job is to forward all\n<code>Dll&shy;Main<\/code> notifications back to your EXE.\nThe DLL would naturally have to have a way for your EXE\nto provide the callback address,\nso\nyou might have a function\n<code>Register&shy;Lackey&shy;Callback<\/code>.\n<\/p>\n<pre>\ntypedef BOOL (CALLBACK *LACKEYNOTIFICATION)(DWORD dwReason);\nLACKEYNOTIFICATION g_lackeyNotification;\nvoid RegisterLackeyCallback(LACKEYNOTIFICATION lackeyNotification)\n{\n g_lackeyNotification = lackeyNotification;\n}\nBOOL WINAPI DllMain(\n    HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)\n{\n if (g_lackeyNotification) g_lackeyNotification(dwReason);\n return TRUE;\n}\n<\/pre>\n<p>\nOf course, it is rather extravagant to hire a lackey just for\nthis one task,\nso you will probably just add lackey responsibilities to\nsome other DLL you&#8217;ve written.\n<\/p>\n<p>\nI don&#8217;t know if there&#8217;s a name for this design pattern,\nso I&#8217;m just going to call it the <i>hired lackey<\/i> pattern.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When a DLL is loaded, it receives a DLL_PROCESS_ATTACH notification, and when it is unloaded (or when the process terminates), it gets a DLL_PROCESS_DETACH notification. DLLs also receive DLL_THREAD_ATTACH notifications when a thread is created and DLL_THREAD_DETACH notifications when a thread exits. But what if you are an EXE? EXEs don&#8217;t have a Dll&shy;Main, so [&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-43833","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>When a DLL is loaded, it receives a DLL_PROCESS_ATTACH notification, and when it is unloaded (or when the process terminates), it gets a DLL_PROCESS_DETACH notification. DLLs also receive DLL_THREAD_ATTACH notifications when a thread is created and DLL_THREAD_DETACH notifications when a thread exits. But what if you are an EXE? EXEs don&#8217;t have a Dll&shy;Main, so [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43833","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=43833"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43833\/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=43833"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=43833"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=43833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}