Add support for call to Register/Unregister COM delegate (dotnet/core-setup#6366)
authorAaron Robinson <arobins@microsoft.com>
Thu, 9 May 2019 18:50:13 +0000 (11:50 -0700)
committerGitHub <noreply@github.com>
Thu, 9 May 2019 18:50:13 +0000 (11:50 -0700)
Commit migrated from https://github.com/dotnet/core-setup/commit/5b1d47b8487b1985f3ed2b3731ce828b8b9118ba

src/installer/corehost/cli/comhost/comhost.cpp
src/installer/corehost/cli/corehost_context_contract.h
src/installer/corehost/cli/fxr/hostfxr.cpp
src/installer/corehost/cli/hostfxr.h
src/installer/corehost/cli/hostpolicy/hostpolicy.cpp

index 63c56c9..7556546 100644 (file)
@@ -42,14 +42,14 @@ struct com_activation_context
     void **class_factory_dest;
 };
 
-using com_activation_fn = int(STDMETHODCALLTYPE*)(com_activation_context*);
+using com_delegate_fn = int(STDMETHODCALLTYPE*)(com_activation_context*);
 
 namespace
 {
-    int get_com_activation_delegate(pal::string_t *app_path, com_activation_fn *delegate)
+    int get_com_delegate(hostfxr_delegate_type del_type, pal::string_t *app_path, com_delegate_fn *delegate)
     {
         return load_fxr_and_get_delegate(
-            hostfxr_delegate_type::com_activation,
+            del_type,
             [app_path](const pal::string_t& host_path, pal::string_t* config_path_out)
             {
                 // Strip the comhost suffix to get the 'app' and config
@@ -108,14 +108,14 @@ COM_API HRESULT STDMETHODCALLTYPE DllGetClassObject(
 
     HRESULT hr;
     pal::string_t app_path;
-    com_activation_fn act;
+    com_delegate_fn act;
     {
         trace::setup();
         reset_redirected_error_writer();
         
         error_writer_scope_t writer_scope(redirected_error_writer);
 
-        int ec = get_com_activation_delegate(&app_path, &act);
+        int ec = get_com_delegate(hostfxr_delegate_type::com_activation, &app_path, &act);
         if (ec != StatusCode::Success)
         {
             report_com_error_info(rclsid, std::move(get_redirected_error_string()));
@@ -317,6 +317,8 @@ COM_API HRESULT STDMETHODCALLTYPE DllRegisterServer(void)
 {
     // Step 0: Initialize logging
     trace::setup();
+    reset_redirected_error_writer();
+    error_writer_scope_t writer_scope(redirected_error_writer);
 
     // Step 1: Get CLSID mapping
     clsid_map map;
@@ -324,11 +326,34 @@ COM_API HRESULT STDMETHODCALLTYPE DllRegisterServer(void)
 
     trace::info(_X("Registering %d CLSIDs"), (int)map.size());
 
-    // Step 2: Register each CLSID
     HRESULT hr;
+    pal::string_t app_path;
+    com_delegate_fn reg;
+    RETURN_IF_FAILED(get_com_delegate(hostfxr_delegate_type::com_register, &app_path, &reg));
+
+    com_activation_context cxt
+    {
+        GUID_NULL,
+        GUID_NULL,  // Must be GUID_NULL
+        app_path.c_str(),
+        nullptr,
+        nullptr,
+        nullptr     // Must be nullptr
+    };
+
+    // Step 2: Register each CLSID
     for (clsid_map::const_reference p : map)
+    {
+        // Register the CLSID in registry
         RETURN_IF_FAILED(RegisterClsid(p.first, _X("Both")));
 
+        // Call user-defined register function
+        cxt.class_id = p.first;
+        cxt.assembly_name = p.second.assembly.c_str();
+        cxt.type_name = p.second.type.c_str();
+        RETURN_IF_FAILED(reg(&cxt));
+    }
+
     return S_OK;
 }
 
@@ -336,15 +361,42 @@ COM_API HRESULT STDMETHODCALLTYPE DllUnregisterServer(void)
 {
     // Step 0: Initialize logging
     trace::setup();
+    reset_redirected_error_writer();
+    error_writer_scope_t writer_scope(redirected_error_writer);
 
     // Step 1: Get CLSID mapping
     clsid_map map;
     RETURN_HRESULT_IF_EXCEPT(map = comhost::get_clsid_map());
 
-    // Step 2: Unregister each CLSID
+    trace::info(_X("Unregistering %d CLSIDs"), (int)map.size());
+
     HRESULT hr;
+    pal::string_t app_path;
+    com_delegate_fn unreg;
+    RETURN_IF_FAILED(get_com_delegate(hostfxr_delegate_type::com_unregister, &app_path, &unreg));
+
+    com_activation_context cxt
+    {
+        GUID_NULL,
+        GUID_NULL,  // Must be GUID_NULL
+        app_path.c_str(),
+        nullptr,
+        nullptr,
+        nullptr     // Must be nullptr
+    };
+
+    // Step 2: Unregister each CLSID
     for (clsid_map::const_reference p : map)
+    {
+        // Call user-defined unregister function
+        cxt.class_id = p.first;
+        cxt.assembly_name = p.second.assembly.c_str();
+        cxt.type_name = p.second.type.c_str();
+        RETURN_IF_FAILED(unreg(&cxt));
+
+        // Unregister the CLSID from registry
         RETURN_IF_FAILED(RemoveClsid(p.first));
+    }
 
     return S_OK;
 }
index be5071e..dfe99c3 100644 (file)
@@ -20,7 +20,9 @@ enum class coreclr_delegate_type
     invalid,
     com_activation,
     load_in_memory_assembly,
-    winrt_activation
+    winrt_activation,
+    com_register,
+    com_unregister
 };
 
 #pragma pack(push, _HOST_INTERFACE_PACK)
index 0f5d757..3472cc4 100644 (file)
@@ -592,6 +592,10 @@ namespace
             return coreclr_delegate_type::load_in_memory_assembly;
         case hostfxr_delegate_type::winrt_activation:
             return coreclr_delegate_type::winrt_activation;
+        case hostfxr_delegate_type::com_register:
+            return coreclr_delegate_type::com_register;
+        case hostfxr_delegate_type::com_unregister:
+            return coreclr_delegate_type::com_unregister;
         }
         return coreclr_delegate_type::invalid;
     }
index bc4ab70..949b8a5 100644 (file)
@@ -20,7 +20,9 @@ enum class hostfxr_delegate_type
 {
     com_activation,
     load_in_memory_assembly,
-    winrt_activation
+    winrt_activation,
+    com_register,
+    com_unregister
 };
 
 using hostfxr_main_fn = int32_t(*)(const int argc, const pal::char_t* argv[]);
index 017909e..0119d3f 100644 (file)
@@ -461,6 +461,18 @@ namespace
                 "Internal.Runtime.InteropServices.WindowsRuntime.ActivationFactoryLoader",
                 "GetActivationFactory",
                 delegate);
+        case coreclr_delegate_type::com_register:
+            return coreclr->create_delegate(
+                "System.Private.CoreLib",
+                "Internal.Runtime.InteropServices.ComActivator",
+                "RegisterClassForTypeInternal",
+                delegate);
+        case coreclr_delegate_type::com_unregister:
+            return coreclr->create_delegate(
+                "System.Private.CoreLib",
+                "Internal.Runtime.InteropServices.ComActivator",
+                "UnregisterClassForTypeInternal",
+                delegate);
         default:
             return StatusCode::LibHostInvalidArgs;
         }