service.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include "./main.h"
  2. #include "./service.h"
  3. #include "./ifc_omservicehost.h"
  4. #include "./ifc_omserviceeventmngr.h"
  5. #include "../winamp/wa_ipc.h"
  6. #include <strsafe.h>
  7. #define DEFAULT_GENERATION 2
  8. #define IS_INVALIDISPATCH(__disp) (((IDispatch *)1) == (__disp) || NULL == (__disp))
  9. OmService::OmService(UINT serviceId, ifc_omservicehost *serviceHost)
  10. : ref(1), id(serviceId), name(NULL), url(NULL), icon(NULL), rating(0), version(0),
  11. flags(0), generation(2), description(NULL), authorFirst(NULL), authorLast(NULL),
  12. published(NULL), updated(NULL), thumbnail(NULL), screenshot(NULL), address(NULL),
  13. host(serviceHost)
  14. {
  15. if (NULL != host)
  16. host->AddRef();
  17. modified.SetEventHandler(ModifiedEvent, (ULONG_PTR)this);
  18. InitializeCriticalSection(&lock);
  19. InitializeCriticalSection(&eventLock);
  20. }
  21. OmService::~OmService()
  22. {
  23. Plugin_FreeString(name);
  24. Plugin_FreeString(url);
  25. Plugin_FreeString(icon);
  26. Plugin_FreeString(address);
  27. Plugin_FreeString(description);
  28. Plugin_FreeString(authorFirst);
  29. Plugin_FreeString(authorLast);
  30. Plugin_FreeString(published);
  31. Plugin_FreeString(updated);
  32. Plugin_FreeString(thumbnail);
  33. Plugin_FreeString(screenshot);
  34. UnregisterAllEventHandlers();
  35. if (NULL != host)
  36. host->Release();
  37. DeleteCriticalSection(&lock);
  38. DeleteCriticalSection(&eventLock);
  39. }
  40. HRESULT OmService::CreateInstance(UINT serviceId, ifc_omservicehost *host, OmService **serviceOut)
  41. {
  42. if (NULL == serviceOut) return E_POINTER;
  43. *serviceOut = new OmService(serviceId, host);
  44. if (NULL == *serviceOut) return E_OUTOFMEMORY;
  45. return S_OK;
  46. }
  47. size_t OmService::AddRef()
  48. {
  49. return InterlockedIncrement((LONG*)&ref);
  50. }
  51. size_t OmService::Release()
  52. {
  53. if (0 == ref)
  54. return ref;
  55. LONG r = InterlockedDecrement((LONG*)&ref);
  56. if (0 == r)
  57. delete(this);
  58. return r;
  59. }
  60. int OmService::QueryInterface(GUID interface_guid, void **object)
  61. {
  62. if (NULL == object) return E_POINTER;
  63. if (IsEqualIID(interface_guid, IFC_OmService))
  64. *object = static_cast<ifc_omservice*>(this);
  65. else if (IsEqualIID(interface_guid, IFC_OmServiceDetails))
  66. *object = static_cast<ifc_omservicedetails*>(this);
  67. else if (IsEqualIID(interface_guid, IFC_OmServiceEditor))
  68. *object = static_cast<ifc_omserviceeditor*>(this);
  69. else if (IsEqualIID(interface_guid, IFC_OmServiceCopier))
  70. *object = static_cast<ifc_omservicecopier*>(this);
  71. else if (IsEqualIID(interface_guid, IFC_OmServiceCommand))
  72. *object = static_cast<ifc_omservicecommand*>(this);
  73. else if (IsEqualIID(interface_guid, IFC_OmServiceEventMngr))
  74. *object = static_cast<ifc_omserviceeventmngr*>(this);
  75. else if (IsEqualIID(interface_guid, IFC_OmServiceHostExt))
  76. *object = static_cast<ifc_omservicehostext*>(this);
  77. else
  78. {
  79. *object = NULL;
  80. return E_NOINTERFACE;
  81. }
  82. if (NULL == *object)
  83. return E_UNEXPECTED;
  84. AddRef();
  85. return S_OK;
  86. }
  87. HRESULT OmService::StringCchCopyExMT(LPTSTR pszDest, size_t cchDest, LPCTSTR pszSrc, LPTSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags)
  88. {
  89. if (NULL == pszDest)
  90. return E_POINTER;
  91. EnterCriticalSection(&lock);
  92. HRESULT hr = StringCchCopyEx(pszDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
  93. LeaveCriticalSection(&lock);
  94. return hr;
  95. }
  96. UINT OmService::GetId()
  97. {
  98. return id;
  99. }
  100. HRESULT OmService::SetId(UINT serviceId)
  101. {
  102. id = serviceId;
  103. return S_OK;
  104. }
  105. HRESULT OmService::GetName(LPWSTR pszBuffer, UINT cchBufferMax)
  106. {
  107. return StringCchCopyExMT(pszBuffer, cchBufferMax, name, NULL, NULL,STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  108. }
  109. HRESULT OmService::GetUrl(LPWSTR pszBuffer, UINT cchBufferMax)
  110. {
  111. EnterCriticalSection(&lock);
  112. HRESULT hr = GetUrlDirect(pszBuffer, cchBufferMax);
  113. if(SUCCEEDED(hr))
  114. {
  115. if (NULL != host)
  116. {
  117. HRESULT hostResult = host->GetUrl(this, pszBuffer, cchBufferMax);
  118. if (FAILED(hostResult) && E_NOTIMPL != hostResult)
  119. hr = hostResult;
  120. }
  121. }
  122. LeaveCriticalSection(&lock);
  123. return hr;
  124. }
  125. HRESULT OmService::GetUrlDirect(LPWSTR pszBuffer, UINT cchBufferMax)
  126. {
  127. return StringCchCopyExMT(pszBuffer, cchBufferMax, url, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  128. }
  129. HRESULT OmService::GetIcon(LPWSTR pszBuffer, UINT cchBufferMax)
  130. {
  131. return StringCchCopyExMT(pszBuffer, cchBufferMax, icon, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  132. }
  133. HRESULT OmService::GetExternal(IDispatch **ppDispatch)
  134. {
  135. if (NULL == ppDispatch)
  136. return E_POINTER;
  137. *ppDispatch = NULL;
  138. HWND hWinamp = NULL;
  139. IDispatch *winampDisp = NULL;
  140. if (SUCCEEDED(Plugin_GetWinampWnd(&hWinamp)) && NULL != hWinamp)
  141. {
  142. EnterCriticalSection(&lock);
  143. UINT generation_cached = generation;
  144. LeaveCriticalSection(&lock);
  145. if (2 == generation_cached)
  146. {
  147. WCHAR szBuffer[64] = {0};
  148. if (SUCCEEDED(StringCchPrintfW(szBuffer, ARRAYSIZE(szBuffer), L"%u", id)))
  149. winampDisp = (IDispatch*)SENDWAIPC(hWinamp, IPC_JSAPI2_GET_DISPATCH_OBJECT, (WPARAM)szBuffer);
  150. }
  151. else if (1 == generation_cached)
  152. {
  153. winampDisp = (IDispatch*)SENDWAIPC(hWinamp, IPC_GET_DISPATCH_OBJECT, 0);
  154. }
  155. if (IS_INVALIDISPATCH(winampDisp))
  156. winampDisp = NULL;
  157. }
  158. *ppDispatch = winampDisp;
  159. EnterCriticalSection(&lock);
  160. ifc_omservicehost *host_cached = host;
  161. if (NULL != host_cached)
  162. host_cached->AddRef();
  163. LeaveCriticalSection(&lock);
  164. if (NULL != host_cached)
  165. {
  166. host_cached->GetExternal(this, ppDispatch);
  167. host_cached->Release();
  168. }
  169. return S_OK;
  170. }
  171. HRESULT OmService::GetRating(UINT *ratingOut)
  172. {
  173. if (NULL == ratingOut)
  174. return E_POINTER;
  175. *ratingOut = rating;
  176. return S_OK;
  177. }
  178. HRESULT OmService::GetVersion(UINT *versionOut)
  179. {
  180. if (NULL == versionOut)
  181. return E_POINTER;
  182. *versionOut = version;
  183. return S_OK;
  184. }
  185. HRESULT OmService::GetGeneration(UINT *generationOut)
  186. {
  187. if (NULL == generationOut)
  188. return E_POINTER;
  189. EnterCriticalSection(&lock);
  190. *generationOut = (0 == generation) ? DEFAULT_GENERATION : generation;
  191. LeaveCriticalSection(&lock);
  192. return S_OK;
  193. }
  194. HRESULT OmService::GetFlags(UINT *flagsOut)
  195. {
  196. if (NULL == flagsOut)
  197. return E_POINTER;
  198. *flagsOut = flags;
  199. return S_OK;
  200. }
  201. HRESULT OmService::UpdateFlags(UINT flagsIn)
  202. {
  203. flags = flagsIn;
  204. return S_OK;
  205. }
  206. HRESULT OmService::SetAddress(LPCWSTR pszAddress)
  207. {
  208. EnterCriticalSection(&lock);
  209. HRESULT hr;
  210. Plugin_FreeString(address);
  211. if (NULL == pszAddress)
  212. {
  213. address = NULL;
  214. hr = S_OK;
  215. }
  216. else
  217. {
  218. address = Plugin_CopyString(pszAddress);
  219. hr = (NULL == address) ? E_OUTOFMEMORY : S_OK;
  220. }
  221. LeaveCriticalSection(&lock);
  222. return hr;
  223. }
  224. HRESULT OmService::GetAddress(LPWSTR pszBuffer, UINT cchBufferMax)
  225. {
  226. return StringCchCopyExMT(pszBuffer, cchBufferMax, address, NULL, NULL,STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  227. }
  228. HRESULT OmService::GetHost(ifc_omservicehost **ppHost)
  229. {
  230. if (NULL == ppHost) return E_POINTER;
  231. EnterCriticalSection(&lock);
  232. *ppHost = host;
  233. if (NULL != host)
  234. host->AddRef();
  235. LeaveCriticalSection(&lock);
  236. return S_OK;
  237. }
  238. HRESULT OmService::SetHost(ifc_omservicehost *serviceHost)
  239. {
  240. EnterCriticalSection(&lock);
  241. if (NULL != host)
  242. host->Release();
  243. host = serviceHost;
  244. if (NULL != host)
  245. host->AddRef();
  246. LeaveCriticalSection(&lock);
  247. return S_OK;
  248. }
  249. void CALLBACK OmService::ModifiedEvent(UINT nMark, FlagTracker *instance, ULONG_PTR user)
  250. {
  251. OmService *service = (OmService*)user;
  252. if (NULL == service) return;
  253. service->Signal_ServiceChange(nMark);
  254. }
  255. HRESULT OmService::CopyTo(ifc_omservice *service, UINT *modifiedFlags)
  256. {
  257. if (NULL == service || id != service->GetId())
  258. return E_INVALIDARG;
  259. HRESULT hr;
  260. ifc_omserviceeditor *editor = NULL;
  261. hr = service->QueryInterface(IFC_OmServiceEditor, (void**)&editor);
  262. if (SUCCEEDED(hr) && editor != NULL)
  263. {
  264. editor->BeginUpdate();
  265. if (FAILED(editor->SetName(name, FALSE))) hr = E_FAIL;
  266. if (FAILED(editor->SetUrl(url, FALSE))) hr = E_FAIL;
  267. if (FAILED(editor->SetIcon(icon, FALSE))) hr = E_FAIL;
  268. if (FAILED(editor->SetRating(rating))) hr = E_FAIL;
  269. if (FAILED(editor->SetVersion(version))) hr = E_FAIL;
  270. if (FAILED(editor->SetFlags(flags, 0xFFFFFFFF))) hr = E_FAIL;
  271. if (FAILED(editor->SetDescription(description, FALSE))) hr = E_FAIL;
  272. if (FAILED(editor->SetAuthorFirst(authorFirst, FALSE))) hr = E_FAIL;
  273. if (FAILED(editor->SetAuthorLast(authorLast, FALSE))) hr = E_FAIL;
  274. if (FAILED(editor->SetUpdated(updated, FALSE))) hr = E_FAIL;
  275. if (FAILED(editor->SetPublished(published, FALSE))) hr = E_FAIL;
  276. if (FAILED(editor->SetThumbnail(thumbnail, FALSE))) hr = E_FAIL;
  277. if (FAILED(editor->SetScreenshot(screenshot, FALSE))) hr = E_FAIL;
  278. if (FAILED(editor->SetGeneration(generation))) hr = E_FAIL;
  279. editor->EndUpdate();
  280. if (NULL != modifiedFlags)
  281. editor->GetModified(modifiedFlags);
  282. editor->Release();
  283. }
  284. return hr;
  285. }
  286. HRESULT OmService::QueryState(HWND hBrowser, const GUID *commandGroup, UINT commandId)
  287. {
  288. HRESULT hr;
  289. EnterCriticalSection(&lock);
  290. if (NULL != host)
  291. hr = host->QueryCommandState(this, hBrowser, commandGroup, commandId);
  292. else
  293. hr = E_NOTIMPL;
  294. LeaveCriticalSection(&lock);
  295. return hr;
  296. }
  297. HRESULT OmService::Exec(HWND hBrowser, const GUID *commandGroup, UINT commandId, ULONG_PTR commandArg)
  298. {
  299. HRESULT hr;
  300. EnterCriticalSection(&lock);
  301. if (NULL != host)
  302. hr = host->ExecuteCommand(this, hBrowser, commandGroup, commandId, commandArg);
  303. else
  304. hr = E_NOTIMPL;
  305. LeaveCriticalSection(&lock);
  306. return hr;
  307. }