AMFDispatch.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "AMFDispatch.h"
  2. AMFDispatch::AMFDispatch(AMFMixedArray *array)
  3. {
  4. object=array;
  5. if (object)
  6. object->AddRef();
  7. refCount=1;
  8. }
  9. AMFDispatch::~AMFDispatch()
  10. {
  11. if (object)
  12. object->Release();
  13. }
  14. STDMETHODIMP AMFDispatch::QueryInterface(REFIID riid, PVOID *ppvObject)
  15. {
  16. if (!ppvObject)
  17. return E_POINTER;
  18. else if (IsEqualIID(riid, IID_IDispatch))
  19. *ppvObject = (IDispatch *)this;
  20. else if (IsEqualIID(riid, IID_IUnknown))
  21. *ppvObject = this;
  22. else
  23. {
  24. *ppvObject = NULL;
  25. return E_NOINTERFACE;
  26. }
  27. AddRef();
  28. return S_OK;
  29. }
  30. ULONG AMFDispatch::AddRef(void)
  31. {
  32. return InterlockedIncrement((volatile LONG *)&refCount);
  33. }
  34. ULONG AMFDispatch::Release(void)
  35. {
  36. ULONG count = InterlockedDecrement((volatile LONG *)&refCount);
  37. if (count == 0)
  38. delete this;
  39. return count;
  40. }
  41. enum
  42. {
  43. DISP_AMF_DEBUGPRINT,
  44. DISP_AMF_MAX,
  45. };
  46. #define CHECK_ID(str, id) if (wcscmp(rgszNames[i], L##str) == 0) { rgdispid[i] = id; continue; }
  47. HRESULT AMFDispatch::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  48. {
  49. bool unknowns = false;
  50. for (unsigned int i = 0;i != cNames;i++)
  51. {
  52. CHECK_ID("DebugPrint", DISP_AMF_DEBUGPRINT)
  53. if (object)
  54. {
  55. //size_t index = object->array.getPosition(rgszNames[i]);
  56. size_t index = 0;
  57. for (auto it = object->array.begin(); it != object->array.end(); it++, index++)
  58. {
  59. if (wcscmp(it->first.c_str(), rgszNames[i]) == 0)
  60. {
  61. break;
  62. }
  63. }
  64. if (index != object->array.size())
  65. {
  66. rgdispid[i] = (DISPID)index + DISP_AMF_MAX;
  67. continue;
  68. }
  69. }
  70. rgdispid[i] = DISPID_UNKNOWN;
  71. unknowns = true;
  72. }
  73. if (unknowns)
  74. return DISP_E_UNKNOWNNAME;
  75. else
  76. return S_OK;
  77. }
  78. HRESULT AMFDispatch::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  79. {
  80. return E_NOTIMPL;
  81. }
  82. HRESULT AMFDispatch::GetTypeInfoCount(unsigned int FAR * pctinfo)
  83. {
  84. return E_NOTIMPL;
  85. }
  86. static void AMFType_To_Variant(AMFType *obj, VARIANT *pvarResult)
  87. {
  88. VariantInit(pvarResult);
  89. switch(obj->type)
  90. {
  91. case AMFType::TYPE_DOUBLE: // double
  92. {
  93. AMFDouble *cast_obj = static_cast<AMFDouble *>(obj);
  94. V_VT(pvarResult) = VT_R8;
  95. V_R8(pvarResult) = cast_obj->val;
  96. }
  97. break;
  98. case AMFType::TYPE_BOOL: // bool
  99. {
  100. AMFBoolean *cast_obj = static_cast<AMFBoolean *>(obj);
  101. V_VT(pvarResult) = VT_BOOL;
  102. V_BOOL(pvarResult) = cast_obj->boolean;
  103. }
  104. break;
  105. case AMFType::TYPE_MOVIE: // movie (basically just a URL)
  106. case AMFType::TYPE_STRING: // string
  107. {
  108. AMFString *cast_obj = static_cast<AMFString *>(obj);
  109. V_VT(pvarResult) = VT_BSTR;
  110. V_BSTR(pvarResult) = SysAllocString(cast_obj->str);
  111. }
  112. break;
  113. case AMFType::TYPE_LONG_STRING: // string
  114. {
  115. AMFLongString *cast_obj = static_cast<AMFLongString *>(obj);
  116. V_VT(pvarResult) = VT_BSTR;
  117. V_BSTR(pvarResult) = SysAllocString(cast_obj->str);
  118. }
  119. break;
  120. case AMFType::TYPE_MIXEDARRAY:
  121. {
  122. AMFMixedArray *cast_obj = static_cast<AMFMixedArray *>(obj);
  123. V_VT(pvarResult) = VT_DISPATCH;
  124. V_DISPATCH(pvarResult) = new AMFDispatch(cast_obj);
  125. }
  126. break;
  127. case AMFType::TYPE_DATE:
  128. {
  129. AMFTime *cast_obj = static_cast<AMFTime *>(obj);
  130. V_VT(pvarResult) = VT_DATE;
  131. V_DATE(pvarResult) = cast_obj->val;
  132. }
  133. break;
  134. case AMFType::TYPE_ARRAY:
  135. {
  136. AMFArray *cast_obj = static_cast<AMFArray *>(obj);
  137. SAFEARRAYBOUND rgsabound[1];
  138. rgsabound[0].lLbound = 0;
  139. rgsabound[0].cElements = (ULONG)cast_obj->array.size();
  140. SAFEARRAY *psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  141. VARIANT **data;
  142. SafeArrayAccessData(psa, (void **)&data);
  143. for (size_t i=0;i!=cast_obj->array.size();i++)
  144. {
  145. AMFType_To_Variant(cast_obj->array[i], data[i]);
  146. }
  147. SafeArrayUnaccessData(psa);
  148. V_VT(pvarResult) = VT_ARRAY;
  149. V_ARRAY(pvarResult) = psa;
  150. }
  151. break;
  152. }
  153. }
  154. HRESULT AMFDispatch::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  155. {
  156. if (pvarResult)
  157. VariantInit(pvarResult);
  158. switch(dispid)
  159. {
  160. case DISP_AMF_DEBUGPRINT:
  161. {
  162. wchar_t debugstring[4096]=L"";
  163. wchar_t *str = debugstring;
  164. size_t len = 4096;
  165. object->DebugPrint(1, str, len);
  166. V_VT(pvarResult) = VT_BSTR;
  167. V_BSTR(pvarResult) = SysAllocString(debugstring);
  168. }
  169. return S_OK;
  170. }
  171. size_t index = dispid - DISP_AMF_MAX;
  172. if (index >= object->array.size())
  173. return DISP_E_MEMBERNOTFOUND;
  174. //AMFType *obj = object->array.at(index).second;
  175. AMFType* obj = 0;
  176. auto it = object->array.begin();
  177. while (index--)
  178. {
  179. it++;
  180. }
  181. if (it != object->array.end())
  182. {
  183. obj = it->second;
  184. }
  185. if (!obj)
  186. return S_OK;
  187. switch(obj->type)
  188. {
  189. case AMFType::TYPE_DOUBLE:
  190. case AMFType::TYPE_BOOL:
  191. case AMFType::TYPE_STRING:
  192. case AMFType::TYPE_MIXEDARRAY:
  193. case AMFType::TYPE_ARRAY:
  194. AMFType_To_Variant(obj, pvarResult);
  195. return S_OK;
  196. case AMFType::TYPE_OBJECT: // object
  197. // TODO
  198. return DISP_E_TYPEMISMATCH;
  199. case AMFType::TYPE_NULL: // null
  200. return S_OK;
  201. case AMFType::TYPE_REFERENCE: // reference
  202. return DISP_E_TYPEMISMATCH;
  203. case AMFType::TYPE_TERMINATOR:
  204. // TODO?
  205. return DISP_E_TYPEMISMATCH;
  206. case AMFType::TYPE_DATE: // date
  207. return DISP_E_TYPEMISMATCH;
  208. case AMFType::TYPE_LONG_STRING: // long string
  209. return DISP_E_TYPEMISMATCH;
  210. case AMFType::TYPE_XML: // XML
  211. return DISP_E_TYPEMISMATCH;
  212. default:
  213. return DISP_E_TYPEMISMATCH;
  214. }
  215. return S_OK;
  216. }