1
0

externalMngr.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. #include "./externalMngr.h"
  2. #include "./common.h"
  3. #include "../../winamp/jsapi.h"
  4. ExternalManager::ExternalManager()
  5. : ref(1), lastDispId(0)
  6. {
  7. InitializeCriticalSection(&lock);
  8. }
  9. ExternalManager::~ExternalManager()
  10. {
  11. EnterCriticalSection(&lock);
  12. size_t index= list.size();
  13. while(index--)
  14. {
  15. if (NULL != list[index].object)
  16. list[index].object->Release();
  17. }
  18. LeaveCriticalSection(&lock);
  19. DeleteCriticalSection(&lock);
  20. }
  21. HRESULT ExternalManager::CreateInstance(ExternalManager **instance)
  22. {
  23. if (NULL == instance) return E_POINTER;
  24. *instance = new ExternalManager();
  25. if (NULL == instance) return E_OUTOFMEMORY;
  26. return S_OK;
  27. }
  28. STDMETHODIMP_(ULONG) ExternalManager::AddRef(void)
  29. {
  30. return InterlockedIncrement((LONG*)&ref);
  31. }
  32. STDMETHODIMP_(ULONG) ExternalManager::Release(void)
  33. {
  34. if (0 == ref)
  35. return ref;
  36. LONG r = InterlockedDecrement((LONG*)&ref);
  37. if (0 == r)
  38. delete(this);
  39. return r;
  40. }
  41. STDMETHODIMP ExternalManager::QueryInterface(REFIID riid, PVOID *ppvObject)
  42. {
  43. if (NULL == ppvObject)
  44. return E_POINTER;
  45. if (IsEqualIID(riid, IID_IDispatchEx))
  46. *ppvObject = static_cast<IDispatchEx*>(this);
  47. else if (IsEqualIID(riid, IID_IDispatch))
  48. *ppvObject = static_cast<IDispatch*>(this);
  49. else if (IsEqualIID(riid, IID_IUnknown))
  50. *ppvObject = static_cast<IUnknown*>(this);
  51. else
  52. {
  53. *ppvObject = NULL;
  54. return E_NOINTERFACE;
  55. }
  56. if (NULL == *ppvObject)
  57. return E_UNEXPECTED;
  58. AddRef();
  59. return S_OK;
  60. }
  61. STDMETHODIMP ExternalManager::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  62. {
  63. EnterCriticalSection(&lock);
  64. UINT unknowns = 0;
  65. size_t count = list.size();
  66. for (UINT i = 0; i != cNames ; i++)
  67. {
  68. rgdispid[i] = DISPID_UNKNOWN;
  69. for (size_t j =0; j < count; j++)
  70. {
  71. if (CSTR_EQUAL == CompareString(lcid, 0, rgszNames[i], -1, list[j].name, -1))
  72. {
  73. if (NULL != list[j].object)
  74. rgdispid[i] = list[j].id;
  75. else
  76. unknowns++;
  77. break;
  78. }
  79. if (DISPID_UNKNOWN == rgdispid[i])
  80. unknowns++;
  81. }
  82. }
  83. LeaveCriticalSection(&lock);
  84. return (0 != unknowns) ? DISP_E_UNKNOWNNAME : S_OK;
  85. }
  86. STDMETHODIMP ExternalManager::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  87. {
  88. return E_NOTIMPL;
  89. }
  90. STDMETHODIMP ExternalManager::GetTypeInfoCount(unsigned int FAR * pctinfo)
  91. {
  92. return E_NOTIMPL;
  93. }
  94. STDMETHODIMP ExternalManager::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  95. {
  96. return InvokeEx(dispid, lcid, wFlags, pdispparams, pvarResult, pexecinfo, 0);
  97. }
  98. STDMETHODIMP ExternalManager::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  99. {
  100. if (NULL == pid) return E_POINTER;
  101. *pid = DISPID_UNKNOWN;
  102. HRESULT hr = DISP_E_UNKNOWNNAME;
  103. if (NULL != bstrName && L'\0' != *bstrName)
  104. {
  105. UINT compareFlags = 0;
  106. if (0 != (fdexNameCaseInsensitive & grfdex))
  107. compareFlags |= NORM_IGNORECASE;
  108. EnterCriticalSection(&lock);
  109. size_t index = list.size();
  110. while(index--)
  111. {
  112. if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, compareFlags, bstrName, -1, list[index].name, -1))
  113. {
  114. if (NULL != list[index].object)
  115. {
  116. *pid = list[index].id;
  117. hr = S_OK;
  118. }
  119. break;
  120. }
  121. }
  122. LeaveCriticalSection(&lock);
  123. }
  124. return hr;
  125. }
  126. STDMETHODIMP ExternalManager::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
  127. {
  128. if (DISPATCH_METHOD == wFlags || DISPATCH_PROPERTYGET == wFlags || DISPATCH_CONSTRUCT == wFlags)
  129. JSAPI_INIT_RESULT(pvarRes, VT_DISPATCH);
  130. HRESULT hr(DISP_E_MEMBERNOTFOUND);
  131. EnterCriticalSection(&lock);
  132. size_t index = list.size();
  133. while(index--)
  134. {
  135. if (id == list[index].id)
  136. {
  137. if (NULL != list[index].object)
  138. {
  139. if (NULL != pvarRes &&
  140. (DISPATCH_METHOD == wFlags || DISPATCH_PROPERTYGET == wFlags || DISPATCH_CONSTRUCT == wFlags))
  141. {
  142. list[index].object->AddRef();
  143. pvarRes->pdispVal = list[index].object;
  144. }
  145. hr = S_OK;
  146. }
  147. break;
  148. }
  149. }
  150. LeaveCriticalSection(&lock);
  151. return hr;
  152. }
  153. STDMETHODIMP ExternalManager::DeleteMemberByName(BSTR bstrName, DWORD grfdex)
  154. {
  155. HRESULT hr = S_FALSE;
  156. if (NULL != bstrName && L'\0' != *bstrName)
  157. {
  158. UINT compareFlags = 0;
  159. if (0 != (fdexNameCaseInsensitive & grfdex))
  160. compareFlags |= NORM_IGNORECASE;
  161. EnterCriticalSection(&lock);
  162. size_t index = list.size();
  163. while(index--)
  164. {
  165. if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, compareFlags, bstrName, -1, list[index].name, -1))
  166. {
  167. if (NULL != list[index].object)
  168. {
  169. list[index].object->Release();
  170. list[index].object = NULL;
  171. hr = S_OK;
  172. }
  173. break;
  174. }
  175. }
  176. LeaveCriticalSection(&lock);
  177. }
  178. return hr;
  179. }
  180. STDMETHODIMP ExternalManager::DeleteMemberByDispID(DISPID id)
  181. {
  182. HRESULT hr = S_FALSE;
  183. EnterCriticalSection(&lock);
  184. size_t index = list.size();
  185. while(index--)
  186. {
  187. if (id == list[index].id)
  188. {
  189. if (NULL != list[index].object)
  190. {
  191. list[index].object->Release();
  192. list[index].object = NULL;
  193. hr = S_OK;
  194. }
  195. break;
  196. }
  197. }
  198. LeaveCriticalSection(&lock);
  199. return hr;
  200. }
  201. STDMETHODIMP ExternalManager::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  202. {
  203. HRESULT hr(DISP_E_UNKNOWNNAME);
  204. EnterCriticalSection(&lock);
  205. size_t index = list.size();
  206. while(index--)
  207. {
  208. if (id == list[index].id)
  209. {
  210. if (NULL != list[index].object)
  211. {
  212. if (NULL != pgrfdex)
  213. {
  214. *pgrfdex = 0;
  215. if (0 != (grfdexPropCanAll & grfdexFetch))
  216. *pgrfdex |= (fdexPropCanGet | fdexPropCanCall);
  217. if (0 != (grfdexPropCannotAll & grfdexFetch))
  218. *pgrfdex |= (fdexPropCannotPut | fdexPropCanPutRef | fdexPropCannotConstruct | fdexPropCannotSourceEvents);
  219. if (0 != (grfdexPropExtraAll & grfdexFetch))
  220. *pgrfdex |= (fdexPropNoSideEffects | fdexPropNoSideEffects);
  221. }
  222. hr = S_OK;
  223. }
  224. break;
  225. }
  226. }
  227. LeaveCriticalSection(&lock);
  228. return hr;
  229. }
  230. STDMETHODIMP ExternalManager::GetMemberName(DISPID id, BSTR *pbstrName)
  231. {
  232. HRESULT hr(DISP_E_UNKNOWNNAME);
  233. EnterCriticalSection(&lock);
  234. size_t index = list.size();
  235. while(index--)
  236. {
  237. if (id == list[index].id)
  238. {
  239. if (NULL != list[index].object)
  240. {
  241. if (NULL != pbstrName)
  242. {
  243. *pbstrName = SysAllocString(list[index].name);
  244. hr = S_OK;
  245. }
  246. }
  247. break;
  248. }
  249. }
  250. LeaveCriticalSection(&lock);
  251. return hr;
  252. }
  253. STDMETHODIMP ExternalManager::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
  254. {
  255. HRESULT hr(S_FALSE);
  256. if (NULL == pid) return S_FALSE;
  257. *pid = DISPID_UNKNOWN;
  258. EnterCriticalSection(&lock);
  259. size_t count = list.size();
  260. if (DISPID_STARTENUM == id)
  261. {
  262. if (count > 0)
  263. {
  264. *pid = list[0].id;
  265. hr = S_OK;
  266. }
  267. }
  268. else
  269. {
  270. for(size_t i = 0; i < count; i++)
  271. {
  272. if (id == list[i].id)
  273. {
  274. i++;
  275. if (i < count)
  276. {
  277. *pid = list[i].id;
  278. hr = S_OK;
  279. }
  280. break;
  281. }
  282. }
  283. }
  284. LeaveCriticalSection(&lock);
  285. return hr;
  286. }
  287. STDMETHODIMP ExternalManager::GetNameSpaceParent(IUnknown **ppunk)
  288. {
  289. return E_NOTIMPL;
  290. }
  291. HRESULT ExternalManager::AddDispatch(LPCWSTR pszName, IDispatch *pDispatch, DISPID *pid)
  292. {
  293. if (NULL != pid)
  294. *pid = DISPID_UNKNOWN;
  295. if (NULL == pszName || L'\0' == pszName || NULL == pDispatch)
  296. return E_INVALIDARG;
  297. HRESULT hr;
  298. EnterCriticalSection(&lock);
  299. size_t index = list.size();
  300. while(index--)
  301. {
  302. if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, pszName, -1, list[index].name, -1))
  303. {
  304. if (NULL != list[index].object)
  305. {
  306. hr = E_FAIL;
  307. }
  308. else
  309. {
  310. list[index].object = pDispatch;
  311. pDispatch->AddRef();
  312. *pid = list[index].id;
  313. hr = S_OK;
  314. }
  315. break;
  316. }
  317. }
  318. if ((size_t)-1 == index)
  319. {
  320. DispatchRecord r;
  321. r.name = LoginBox_CopyString(pszName);
  322. if (NULL == r.name)
  323. hr = E_OUTOFMEMORY;
  324. else
  325. {
  326. r.id = ++lastDispId;
  327. r.object = pDispatch;
  328. pDispatch->AddRef();
  329. list.push_back(r);
  330. *pid = r.id;
  331. hr = S_OK;
  332. }
  333. }
  334. LeaveCriticalSection(&lock);
  335. return hr;
  336. }