
{"id":16,"date":"2008-02-04T23:24:06","date_gmt":"2008-02-05T04:24:06","guid":{"rendered":"http:\/\/ikriv.com:8765\/blog\/?p=16"},"modified":"2008-02-04T23:24:06","modified_gmt":"2008-02-05T04:24:06","slug":"unmanaged-hosting-api-gotcha","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=16","title":{"rendered":"Unmanaged Hosting API Gotcha"},"content":{"rendered":"<p>I was playing with .NET 2.0 unmanaged hosting API. I am trying to customize assembly loading and &#8220;fix&#8221; some assemblies on the fly. I found an interesting gotcha, that I want to write down.<\/p>\n<p>In one line: if you return a non-null value from <code>IHostAssemblyManager::GetNonHostStoreAssemblies<\/code>, then <code>ICLRRuntimeHost::ExecuteInDefaultAppDomain<\/code> returns error code 0x80131051 or <code>FUSION_E_LOADFROM_BLOCKED<\/code>, without ever consulting your assembly store, or the non-host store assemblies list.<\/p>\n<p><!--more--><\/p>\n<p>The CLR hosting API is very well structured. You start with <code>CorBindToRuntimeEx<\/code> call, followed by <code>ICLRRuntimeHost::SetHostControl<\/code>, and then CLR will ask your host to provide a number of &#8220;managers&#8221;, such as memory manager, assembly manager, etc. All managers are optional: you may return E_NOINTERFACE to let CLR do the default thing.<\/p>\n<p>Naturally, I was interested in the assembly manager that implements <code>IHostAssemblyManager<\/code> interface. This interface returns two objects to the CLR: the assembly store, that knows how to get assemblies, and the list of &#8220;non host store assemblies&#8221; that the CLR should be able to load by itself. The <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms164460.aspx\">documentation<\/a> says that the CLR behaves differently depending on whether non host store assemblies list is NULL or not, but it describes only the differences in assembly loading order.<\/p>\n<p>What it does not describe, is that if you return a non-NULL for &#8220;non host store assemblies list&#8221;, an internal variable <code>g_bFusionHosted<\/code> is set to <code>true<\/code>, and the method <code>CorHost2::IsLoadFromBlocked<\/code> returns <code>true<\/code>. This means that whenever you try to load an assembly from a particular path, you will get return code <code>FUSION_E_LOADFROM_BLOCKED<\/code>, or 0x80131051.<\/p>\n<p>In particular, <code>ExecuteInDefaultAppDomain<\/code> will fail with this error code, because it loads assembly from a path. Even if you don&#8217;t specify the path, and don&#8217;t specify the extension, it still fails.<\/p>\n<p>Note, that all that matters is a non-null value of the &#8220;non host store assemblies list&#8221;. If you call <code>ExecuteInDefaultAppDomain<\/code> the CLR never actually consults this list. You may even pass any garbage value instead of the real list, the result will still be the same.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was playing with .NET 2.0 unmanaged hosting API. I am trying to customize assembly loading and &#8220;fix&#8221; some assemblies on the fly. I found an interesting gotcha, that I <a href=\"https:\/\/ikriv.com\/blog\/?p=16\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[3,7,4],"tags":[],"class_list":["entry","author-ikriv","has-more-link","post-16","post","type-post","status-publish","format-standard","category-dotnet","category-cpp","category-hack"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=16"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/16\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}