1 /***
2 *appdomain.h
3 *
4 *           Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:     Utitily for cross App Domain Calls
7 *
8 *           [Public]
9 *
10 ****/
11
12 #pragma once
13
14 #if !defined(_INC_MSCLR_APPDOMAIN)
15
16 #ifndef __cplusplus_cli
17 #error ERROR: msclr libraries require /clr and are not compatible with /clr:oldSyntax
18 #endif
19
20 #ifdef _M_CEE_PURE
21 #error ERROR: msclr appdomain helpers can only be used in mixed mode. Use a cross-domain delegate in pure mode 
22 #endif
23 #include <mscoree.h>
24 #include <crtdbg.h>
25
26 #if defined(_M_IX86)
27 #define _MSCLR_STDCALL_DISTINCT 1
28 #elif defined(_M_IA64)
29 #define _MSCLR_STDCALL_DISTINCT 0
30 #elif defined(_M_AMD64)
31 #define _MSCLR_STDCALL_DISTINCT 0
32 #else 
33 #error Need to add setting for different CPU
34 #endif
35
36 namespace msclr
37 {
38
39 namespace _detail
40 {
41
42 /* helper functions */
43
44 inline
45 void validate(HRESULT hr)
46 {
47       _ASSERT(SUCCEEDED(hr));
48       if (FAILED(hr))
49       {
50              System::Runtime::InteropServices::Marshal::ThrowExceptionForHR(hr);
51       }
52 }
53
54 inline
55 ICLRRuntimeHost *get_clr_runtime_host(void)
56 {
57       ICLRRuntimeHost *pClrHost = NULL;
58
59       HRESULT hr = CorBindToRuntimeEx(
60              NULL,                                      // version of the runtime to request
61              NULL,                                      // flavor of the runtime to request
62              0,                                           // runtime startup flags
63              CLSID_CLRRuntimeHost,           // clsid of ICLRRuntimeHost
64              IID_ICLRRuntimeHost,             // IID of ICLRRuntimeHost
65              (PVOID*)&pClrHost);               // a pointer to our punk that we get back
66
67       if (FAILED(hr))
68       {
69              if (pClrHost != NULL)
70              {
71                     pClrHost->Release();
72              }
73              validate(hr);
74       }
75       return pClrHost;
76 }
77
78 /* callback struct */
79
80 /* __stdcall version */
81
82 #if _MSCLR_STDCALL_DISTINCT
83
84 template <typename RetType>
85 struct callback_stdcall_struct0
86 {
87       RetType (__stdcall *func)();
88       RetType retValue;
89
90       static HRESULT __stdcall callback(void *cookie)
91       {
92              HRESULT hr = E_FAIL;
93              if (cookie == NULL)
94              {
95                     return hr;
96              }
97              callback_stdcall_struct0 *pcs = (callback_stdcall_struct0*)cookie;
98              pcs->retValue = pcs->func();
99              hr = S_OK;
100              return hr;
101       }
102 };
103
104 template <typename RetType, typename ArgType1>
105 struct callback_stdcall_struct1
106 {
107       RetType (__stdcall *func)(ArgType1);
108       RetType retValue;
109       ArgType1 arg1;
110
111       static HRESULT __stdcall callback(void *cookie)
112       {
113              HRESULT hr = E_FAIL;
114              if (cookie == NULL)
115              {
116                     return hr;
117              }
118              callback_stdcall_struct1 *pcs = (callback_stdcall_struct1*)cookie;
119              pcs->retValue = pcs->func(pcs->arg1);
120              hr = S_OK;
121              return hr;
122       }
123 };
124
125 template <typename RetType, typename ArgType1, typename ArgType2>
126 struct callback_stdcall_struct2
127 {
128       RetType (__stdcall *func)(ArgType1, ArgType2);
129       RetType retValue;
130       ArgType1 arg1;
131       ArgType2 arg2;
132
Lines 133 ... 1767 are skipped.
1768              HRESULT hr = E_FAIL;
1769              if (cookie == NULL)
1770              {
1771                     return hr;
1772              }
1773              callback_cdecl_void_struct14 *pcs = (callback_cdecl_void_struct14*)cookie;
1774              pcs->func(pcs->arg1, pcs->arg2, pcs->arg3, pcs->arg4, pcs->arg5, pcs->arg6, pcs->arg7, pcs->arg8, pcs->arg9, pcs->arg10, pcs->arg11, pcs->arg12, pcs->arg13, pcs->arg14);
1775              hr = S_OK;
1776              return hr;
1777       }
1778 };
1779
1780 template <typename ArgType1, typename ArgType2, typename ArgType3, typename ArgType4, typename ArgType5, typename ArgType6, typename ArgType7, typename ArgType8, typename ArgType9, typename ArgType10, typename ArgType11, typename ArgType12, typename ArgType13, typename ArgType14, typename ArgType15>
1781 struct callback_cdecl_void_struct15
1782 {
1783       void (__cdecl * func)(ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15);
1784       ArgType1 arg1;
1785       ArgType2 arg2;
1786       ArgType3 arg3;
1787       ArgType4 arg4;
1788       ArgType5 arg5;
1789       ArgType6 arg6;
1790       ArgType7 arg7;
1791       ArgType8 arg8;
1792       ArgType9 arg9;
1793       ArgType10 arg10;
1794       ArgType11 arg11;
1795       ArgType12 arg12;
1796       ArgType13 arg13;
1797       ArgType14 arg14;
1798       ArgType15 arg15;
1799
1800       static HRESULT __stdcall callback(void *cookie)
1801       {
1802              HRESULT hr = E_FAIL;
1803              if (cookie == NULL)
1804              {
1805                     return hr;
1806              }
1807              callback_cdecl_void_struct15 *pcs = (callback_cdecl_void_struct15*)cookie;
1808              pcs->func(pcs->arg1, pcs->arg2, pcs->arg3, pcs->arg4, pcs->arg5, pcs->arg6, pcs->arg7, pcs->arg8, pcs->arg9, pcs->arg10, pcs->arg11, pcs->arg12, pcs->arg13, pcs->arg14, pcs->arg15);
1809              hr = S_OK;
1810         return hr;
1811     }
1812 };
1813
1814 } // namespace _detail
1815
1816 /* __stdcall version */
1817 #if _MSCLR_STDCALL_DISTINCT
1818
1819 template <typename RetType>
1820 RetType inline call_in_appdomain(DWORD dwAppDomainId, RetType (__stdcall * func)())
1821 {
1822       ICLRRuntimeHost *pClrHost = _detail::get_clr_runtime_host();
1823       _detail::callback_stdcall_struct0<RetType> cs;
1824
1825       // fill up the callback_stdcall_struct
1826       cs.func = func;
1827
1828       // call the function
1829       HRESULT hr = pClrHost->ExecuteInAppDomain(dwAppDomainId, &cs.callback, &cs);
1830       pClrHost->Release();
1831       _detail::validate(hr);
1832       
1833       return cs.retValue;
1834 }
1835
1836 template <typename RetType, typename ArgType1>
1837 RetType inline call_in_appdomain(DWORD dwAppDomainId, RetType (__stdcall * func)(ArgType1), ArgType1 arg1)
1838 {
1839       ICLRRuntimeHost *pClrHost = _detail::get_clr_runtime_host();
1840       _detail::callback_stdcall_struct1<RetType, ArgType1> cs;
1841
1842       // fill up the callback_stdcall_struct
1843       cs.func = func;
1844       cs.arg1 = arg1;
1845
1846       // call the function
1847       HRESULT hr = pClrHost->ExecuteInAppDomain(dwAppDomainId, &cs.callback, &cs);
1848       pClrHost->Release();
1849       _detail::validate(hr);
1850       
1851       return cs.retValue;
1852 }
1853
1854 template <typename RetType, typename ArgType1, typename ArgType2>
1855 RetType inline call_in_appdomain(DWORD dwAppDomainId, RetType (__stdcall * func)(ArgType1, ArgType2), ArgType1 arg1, ArgType2 arg2)
1856 {
1857       ICLRRuntimeHost *pClrHost = _detail::get_clr_runtime_host();
1858       _detail::callback_stdcall_struct2<RetType, ArgType1, ArgType2> cs;
1859
1860       // fill up the callback_stdcall_struct
1861       cs.func = func;
1862       cs.arg1 = arg1;
1863       cs.arg2 = arg2;
1864
1865       // call the function
1866       HRESULT hr = pClrHost->ExecuteInAppDomain(dwAppDomainId, &cs.callback, &cs);
1867       pClrHost->Release();
Lines 1868 ... 3277 are skipped.
3278       cs.arg5 = arg5;
3279       cs.arg6 = arg6;
3280       cs.arg7 = arg7;
3281       cs.arg8 = arg8;
3282       cs.arg9 = arg9;
3283       cs.arg10 = arg10;
3284       cs.arg11 = arg11;
3285       cs.arg12 = arg12;
3286       cs.arg13 = arg13;
3287       cs.arg14 = arg14;
3288
3289       // call the function
3290       HRESULT hr = pClrHost->ExecuteInAppDomain(dwAppDomainId, &cs.callback, &cs);
3291       pClrHost->Release();
3292       _detail::validate(hr);
3293 }
3294
3295 template <typename ArgType1, typename ArgType2, typename ArgType3, typename ArgType4, typename ArgType5, typename ArgType6, typename ArgType7, typename ArgType8, typename ArgType9, typename ArgType10, typename ArgType11, typename ArgType12, typename ArgType13, typename ArgType14, typename ArgType15>
3296 void inline call_in_appdomain(DWORD dwAppDomainId, void (__cdecl * func)(ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15), ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15)
3297 {
3298       ICLRRuntimeHost *pClrHost = _detail::get_clr_runtime_host();
3299       _detail::callback_cdecl_void_struct15<ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15> cs;
3300
3301       // fill up the callback_cdecl_struct
3302       cs.func = func;
3303       cs.arg1 = arg1;
3304       cs.arg2 = arg2;
3305       cs.arg3 = arg3;
3306       cs.arg4 = arg4;
3307       cs.arg5 = arg5;
3308       cs.arg6 = arg6;
3309       cs.arg7 = arg7;
3310       cs.arg8 = arg8;
3311       cs.arg9 = arg9;
3312       cs.arg10 = arg10;
3313       cs.arg11 = arg11;
3314       cs.arg12 = arg12;
3315       cs.arg13 = arg13;
3316       cs.arg14 = arg14;
3317       cs.arg15 = arg15;
3318
3319       // call the function
3320       HRESULT hr = pClrHost->ExecuteInAppDomain(dwAppDomainId, &cs.callback, &cs);
3321       pClrHost->Release();
3322       _detail::validate(hr);
3323 }
3324
3325 } // namespace msclr
3326
3327 #define _INC_MSCLR_APPDOMAIN
3328
3329 #endif // _INC_MSCLR_APPDOMAIN
3330