COM.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include "il2cpp-config.h"
  2. #include "il2cpp-object-internals.h"
  3. #include "vm/Array.h"
  4. #include "vm/COM.h"
  5. #include "vm/Exception.h"
  6. #include "vm/PlatformInvoke.h"
  7. #include "vm/Reflection.h"
  8. #include "os/COM.h"
  9. namespace il2cpp
  10. {
  11. namespace vm
  12. {
  13. void COM::MarshalVariant(Il2CppObject* obj, Il2CppVariant* variant)
  14. {
  15. IL2CPP_ASSERT(variant);
  16. os::COM::VariantInit(variant);
  17. if (!obj)
  18. return;
  19. if (obj->klass == il2cpp_defaults.sbyte_class)
  20. {
  21. variant->n1.n2.type = IL2CPP_VT_I1;
  22. variant->n1.n2.n3.cVal = *static_cast<int8_t*>(Object::Unbox(obj));
  23. }
  24. else if (obj->klass == il2cpp_defaults.byte_class)
  25. {
  26. variant->n1.n2.type = IL2CPP_VT_UI1;
  27. variant->n1.n2.n3.bVal = *static_cast<uint8_t*>(Object::Unbox(obj));
  28. }
  29. else if (obj->klass == il2cpp_defaults.int16_class)
  30. {
  31. variant->n1.n2.type = IL2CPP_VT_I2;
  32. variant->n1.n2.n3.iVal = *static_cast<int16_t*>(Object::Unbox(obj));
  33. }
  34. else if (obj->klass == il2cpp_defaults.uint16_class)
  35. {
  36. variant->n1.n2.type = IL2CPP_VT_UI2;
  37. variant->n1.n2.n3.uiVal = *static_cast<uint16_t*>(Object::Unbox(obj));
  38. }
  39. else if (obj->klass == il2cpp_defaults.int32_class)
  40. {
  41. variant->n1.n2.type = IL2CPP_VT_I4;
  42. variant->n1.n2.n3.lVal = *static_cast<int32_t*>(Object::Unbox(obj));
  43. }
  44. else if (obj->klass == il2cpp_defaults.uint32_class)
  45. {
  46. variant->n1.n2.type = IL2CPP_VT_UI4;
  47. variant->n1.n2.n3.ulVal = *static_cast<uint32_t*>(Object::Unbox(obj));
  48. }
  49. else if (obj->klass == il2cpp_defaults.int64_class)
  50. {
  51. variant->n1.n2.type = IL2CPP_VT_I8;
  52. variant->n1.n2.n3.llVal = *static_cast<int64_t*>(Object::Unbox(obj));
  53. }
  54. else if (obj->klass == il2cpp_defaults.uint64_class)
  55. {
  56. variant->n1.n2.type = IL2CPP_VT_UI8;
  57. variant->n1.n2.n3.ullVal = *static_cast<uint64_t*>(Object::Unbox(obj));
  58. }
  59. else if (obj->klass == il2cpp_defaults.single_class)
  60. {
  61. variant->n1.n2.type = IL2CPP_VT_R4;
  62. variant->n1.n2.n3.fltVal = *static_cast<float*>(Object::Unbox(obj));
  63. }
  64. else if (obj->klass == il2cpp_defaults.double_class)
  65. {
  66. variant->n1.n2.type = IL2CPP_VT_R8;
  67. variant->n1.n2.n3.dblVal = *static_cast<double*>(Object::Unbox(obj));
  68. }
  69. else if (obj->klass == il2cpp_defaults.boolean_class)
  70. {
  71. variant->n1.n2.type = IL2CPP_VT_BOOL;
  72. variant->n1.n2.n3.boolVal = *static_cast<bool*>(Object::Unbox(obj)) ? IL2CPP_VARIANT_TRUE : IL2CPP_VARIANT_FALSE;
  73. }
  74. else if (obj->klass == il2cpp_defaults.string_class)
  75. {
  76. variant->n1.n2.type = IL2CPP_VT_BSTR;
  77. variant->n1.n2.n3.bstrVal = PlatformInvoke::MarshalCSharpStringToCppBString(reinterpret_cast<Il2CppString*>(obj));
  78. }
  79. else if (obj->klass == il2cpp_defaults.dbnull_class)
  80. {
  81. variant->n1.n2.type = IL2CPP_VT_NULL;
  82. }
  83. else if (obj->klass == il2cpp_defaults.error_wrapper_class)
  84. {
  85. variant->n1.n2.type = IL2CPP_VT_ERROR;
  86. variant->n1.n2.n3.scode = reinterpret_cast<Il2CppErrorWrapper*>(obj)->errorCode;
  87. }
  88. else if (obj->klass == il2cpp_defaults.missing_class)
  89. {
  90. variant->n1.n2.type = IL2CPP_VT_ERROR;
  91. variant->n1.n2.n3.scode = IL2CPP_DISP_E_PARAMNOTFOUND;
  92. }
  93. else
  94. {
  95. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  96. }
  97. }
  98. Il2CppObject* COM::MarshalVariantResult(const Il2CppVariant* variant)
  99. {
  100. IL2CPP_ASSERT(variant);
  101. switch (variant->n1.n2.type)
  102. {
  103. case IL2CPP_VT_EMPTY:
  104. return NULL;
  105. case IL2CPP_VT_NULL:
  106. return Reflection::GetDBNullObject();
  107. case IL2CPP_VT_ERROR:
  108. {
  109. int32_t val = variant->n1.n2.n3.scode;
  110. return Object::Box(il2cpp_defaults.int32_class, &val);
  111. }
  112. case IL2CPP_VT_I1:
  113. {
  114. char val = variant->n1.n2.n3.cVal;
  115. return Object::Box(il2cpp_defaults.sbyte_class, &val);
  116. }
  117. case IL2CPP_VT_UI1:
  118. {
  119. uint8_t val = variant->n1.n2.n3.bVal;
  120. return Object::Box(il2cpp_defaults.byte_class, &val);
  121. }
  122. case IL2CPP_VT_I2:
  123. {
  124. int16_t val = variant->n1.n2.n3.iVal;
  125. return Object::Box(il2cpp_defaults.int16_class, &val);
  126. }
  127. case IL2CPP_VT_UI2:
  128. {
  129. uint16_t val = variant->n1.n2.n3.uiVal;
  130. return Object::Box(il2cpp_defaults.uint16_class, &val);
  131. }
  132. case IL2CPP_VT_I4:
  133. {
  134. int32_t val = variant->n1.n2.n3.lVal;
  135. return Object::Box(il2cpp_defaults.int32_class, &val);
  136. }
  137. case IL2CPP_VT_UI4:
  138. {
  139. uint32_t val = variant->n1.n2.n3.ulVal;
  140. return Object::Box(il2cpp_defaults.uint32_class, &val);
  141. }
  142. case IL2CPP_VT_I8:
  143. {
  144. int64_t val = variant->n1.n2.n3.llVal;
  145. return Object::Box(il2cpp_defaults.int64_class, &val);
  146. }
  147. case IL2CPP_VT_UI8:
  148. {
  149. uint64_t val = variant->n1.n2.n3.ullVal;
  150. return Object::Box(il2cpp_defaults.uint64_class, &val);
  151. }
  152. case IL2CPP_VT_R4:
  153. {
  154. float val = variant->n1.n2.n3.fltVal;
  155. return Object::Box(il2cpp_defaults.single_class, &val);
  156. }
  157. case IL2CPP_VT_R8:
  158. {
  159. double val = variant->n1.n2.n3.dblVal;
  160. return Object::Box(il2cpp_defaults.double_class, &val);
  161. }
  162. case IL2CPP_VT_BOOL:
  163. {
  164. IL2CPP_ASSERT(variant->n1.n2.n3.boolVal == IL2CPP_VARIANT_FALSE || variant->n1.n2.n3.boolVal == IL2CPP_VARIANT_TRUE);
  165. bool value = variant->n1.n2.n3.boolVal != IL2CPP_VARIANT_FALSE;
  166. return Object::Box(il2cpp_defaults.boolean_class, &value);
  167. }
  168. case IL2CPP_VT_BSTR:
  169. return reinterpret_cast<Il2CppObject*>(PlatformInvoke::MarshalCppBStringToCSharpStringResult(variant->n1.n2.n3.bstrVal));
  170. default:
  171. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  172. return NULL;
  173. }
  174. }
  175. void COM::DestroyVariant(Il2CppVariant* variant)
  176. {
  177. const il2cpp_hresult_t hr = os::COM::VariantClear(variant);
  178. vm::Exception::RaiseIfFailed(hr, true);
  179. }
  180. Il2CppSafeArray* COM::MarshalSafeArray(uint16_t variantType, Il2CppArray* managedArray)
  181. {
  182. if (!managedArray)
  183. return NULL;
  184. Il2CppSafeArrayBound bounds[1];
  185. bounds[0].element_count = Array::GetLength(managedArray);
  186. bounds[0].lower_bound = 0;
  187. Il2CppSafeArray* safeArray = os::COM::SafeArrayCreate(variantType, 1, bounds);
  188. if (!safeArray)
  189. Exception::Raise(IL2CPP_E_OUTOFMEMORY, true);
  190. void* data;
  191. il2cpp_hresult_t hr = os::COM::SafeArrayAccessData(safeArray, &data);
  192. if (IL2CPP_HR_FAILED(hr))
  193. {
  194. os::COM::SafeArrayDestroy(safeArray);
  195. Exception::Raise(hr, true);
  196. }
  197. ::memcpy(data, Array::GetFirstElementAddress(managedArray), Array::GetByteLength(managedArray));
  198. hr = os::COM::SafeArrayUnaccessData(safeArray);
  199. if (IL2CPP_HR_FAILED(hr))
  200. {
  201. os::COM::SafeArrayDestroy(safeArray);
  202. Exception::Raise(hr, true);
  203. }
  204. return safeArray;
  205. }
  206. Il2CppArray* COM::MarshalSafeArrayResult(uint16_t variantType, Il2CppClass* type, Il2CppSafeArray* safeArray)
  207. {
  208. if (!safeArray)
  209. return NULL;
  210. uint16_t actualVariantType;
  211. il2cpp_hresult_t hr = os::COM::SafeArrayGetVartype(safeArray, &actualVariantType);
  212. vm::Exception::RaiseIfFailed(hr, true);
  213. if (actualVariantType != variantType)
  214. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  215. const uint32_t actualDimentionCount = os::COM::SafeArrayGetDim(safeArray);
  216. if (actualDimentionCount != 1)
  217. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  218. int32_t lowerBound;
  219. hr = os::COM::SafeArrayGetLBound(safeArray, 1, &lowerBound);
  220. vm::Exception::RaiseIfFailed(hr, true);
  221. int32_t upperBound;
  222. hr = os::COM::SafeArrayGetUBound(safeArray, 1, &upperBound);
  223. vm::Exception::RaiseIfFailed(hr, true);
  224. const il2cpp_array_size_t size = static_cast<il2cpp_array_size_t>(upperBound - lowerBound + 1);
  225. Il2CppArray* managedArray = Array::New(type, size);
  226. void* data;
  227. hr = os::COM::SafeArrayAccessData(safeArray, &data);
  228. vm::Exception::RaiseIfFailed(hr, true);
  229. ::memcpy(Array::GetFirstElementAddress(managedArray), data, Array::GetByteLength(managedArray));
  230. hr = os::COM::SafeArrayUnaccessData(safeArray);
  231. vm::Exception::RaiseIfFailed(hr, true);
  232. return managedArray;
  233. }
  234. Il2CppSafeArray* COM::MarshalSafeArrayBString(Il2CppArray* managedArray)
  235. {
  236. if (!managedArray)
  237. return NULL;
  238. const uint32_t size = Array::GetLength(managedArray);
  239. Il2CppSafeArrayBound bounds[1];
  240. bounds[0].element_count = size;
  241. bounds[0].lower_bound = 0;
  242. Il2CppSafeArray* safeArray = os::COM::SafeArrayCreate(IL2CPP_VT_BSTR, 1, bounds);
  243. if (!safeArray)
  244. Exception::Raise(IL2CPP_E_OUTOFMEMORY, true);
  245. Il2CppChar** data;
  246. il2cpp_hresult_t hr = os::COM::SafeArrayAccessData(safeArray, reinterpret_cast<void**>(&data));
  247. if (IL2CPP_HR_FAILED(hr))
  248. {
  249. os::COM::SafeArrayDestroy(safeArray);
  250. Exception::Raise(hr, true);
  251. }
  252. for (uint32_t i = 0; i < size; ++i)
  253. {
  254. Il2CppString* managedString = il2cpp_array_get(managedArray, Il2CppString*, i);
  255. hr = PlatformInvoke::MarshalCSharpStringToCppBStringNoThrow(managedString, data + i);
  256. if (IL2CPP_HR_FAILED(hr))
  257. {
  258. os::COM::SafeArrayUnaccessData(safeArray);
  259. os::COM::SafeArrayDestroy(safeArray);
  260. Exception::Raise(hr, true);
  261. }
  262. }
  263. hr = os::COM::SafeArrayUnaccessData(safeArray);
  264. if (IL2CPP_HR_FAILED(hr))
  265. {
  266. os::COM::SafeArrayDestroy(safeArray);
  267. Exception::Raise(hr, true);
  268. }
  269. return safeArray;
  270. }
  271. Il2CppArray* COM::MarshalSafeArrayBStringResult(Il2CppClass* type, Il2CppSafeArray* safeArray)
  272. {
  273. if (!safeArray)
  274. return NULL;
  275. uint16_t actualVariantType;
  276. il2cpp_hresult_t hr = os::COM::SafeArrayGetVartype(safeArray, &actualVariantType);
  277. vm::Exception::RaiseIfFailed(hr, true);
  278. if (actualVariantType != IL2CPP_VT_BSTR)
  279. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  280. const uint32_t actualDimentionCount = os::COM::SafeArrayGetDim(safeArray);
  281. if (actualDimentionCount != 1)
  282. Exception::Raise(IL2CPP_E_INVALIDARG, true);
  283. int32_t lowerBound;
  284. hr = os::COM::SafeArrayGetLBound(safeArray, 1, &lowerBound);
  285. vm::Exception::RaiseIfFailed(hr, true);
  286. int32_t upperBound;
  287. hr = os::COM::SafeArrayGetUBound(safeArray, 1, &upperBound);
  288. vm::Exception::RaiseIfFailed(hr, true);
  289. const il2cpp_array_size_t size = static_cast<il2cpp_array_size_t>(upperBound - lowerBound + 1);
  290. Il2CppArray* managedArray = Array::New(il2cpp_defaults.string_class, size);
  291. Il2CppChar** data;
  292. hr = os::COM::SafeArrayAccessData(safeArray, reinterpret_cast<void**>(&data));
  293. vm::Exception::RaiseIfFailed(hr, true);
  294. for (il2cpp_array_size_t i = 0; i < size; ++i)
  295. il2cpp_array_setref(managedArray, i, PlatformInvoke::MarshalCppBStringToCSharpStringResult(data[i]));
  296. hr = os::COM::SafeArrayUnaccessData(safeArray);
  297. vm::Exception::RaiseIfFailed(hr, true);
  298. return managedArray;
  299. }
  300. } /* namespace vm */
  301. } /* namespace il2cpp */