ApplicationCOM.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author: Ben Allison [email protected]
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "ApplicationCOM.h"
  10. #include "../nu/AutoWide.h"
  11. #include "../nu/AutoChar.h"
  12. #include "../nu/ns_wc.h"
  13. #include "api.h"
  14. #include "../Plugins/General/gen_ml/ml.h"
  15. #include <api/syscb/callbacks/browsercb.h>
  16. #include "../Agave/Language/api_language.h"
  17. HINSTANCE WASABI_API_LNG_HINST;
  18. HINSTANCE WASABI_API_ORIG_HINST;
  19. #include <shlwapi.h>
  20. #include "TempFileCOM.h"
  21. #include "resource.h"
  22. #include "JSAPI.h"
  23. #define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
  24. bool FilterUrl(const wchar_t *url)
  25. {
  26. const wchar_t filterNowPlaying[] = L"http://client.winamp.com/nowplaying";
  27. size_t urlLength, filterLength;
  28. if (NULL == url)
  29. return false;
  30. urlLength = lstrlenW(url);
  31. filterLength = ARRAYSIZE(filterNowPlaying) - 1;
  32. if (urlLength >= filterLength &&
  33. CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE,
  34. url, (int)filterLength, filterNowPlaying, (int)filterLength))
  35. {
  36. return true;
  37. }
  38. return false;
  39. }
  40. void myOpenURL(HWND hwnd, const wchar_t *loc)
  41. {
  42. if (loc)
  43. {
  44. bool override=false;
  45. WASABI_API_SYSCB->syscb_issueCallback(SysCallback::BROWSER, BrowserCallback::ONOPENURL, reinterpret_cast<intptr_t>(loc), reinterpret_cast<intptr_t>(&override));
  46. if (!override && false == FilterUrl(loc))
  47. ShellExecuteW(hwnd, L"open", loc, NULL, NULL, SW_SHOWNORMAL);
  48. }
  49. }
  50. void myOpenURLWithFallback(HWND hwnd, wchar_t *loc, wchar_t *fallbackLoc)
  51. {
  52. bool override=false;
  53. if (loc)
  54. {
  55. WASABI_API_SYSCB->syscb_issueCallback(SysCallback::BROWSER, BrowserCallback::ONOPENURL, reinterpret_cast<intptr_t>(loc), reinterpret_cast<intptr_t>(&override));
  56. }
  57. if (!override && false == FilterUrl(loc) && fallbackLoc)
  58. ShellExecuteW(hwnd, L"open", fallbackLoc, NULL, NULL, SW_SHOWNORMAL);
  59. }
  60. enum
  61. {
  62. DISP_APPLICATION_IDLE = 777,
  63. DISP_APPLICATION_GETLANGUAGE,
  64. DISP_APPLICATION_ISWINAMPPRO,
  65. DISP_APPLICATION_GETCOUNTRY,
  66. DISP_APPLICATION_GETLOCALE,
  67. DISP_APPLICATION_LAUNCHURL,
  68. DISP_APPLICATION_VERSION,
  69. DISP_APPLICATION_SPECIALBUILD,
  70. DISP_APPLICATION_DOWNLOADMEDIA,
  71. DISP_APPLICATION_CREATETEMPFILE,
  72. };
  73. #define CHECK_ID(str, id)\
  74. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, rgszNames[i], -1, L##str, -1))\
  75. { rgdispid[i] = id; continue; }
  76. HRESULT ApplicationCOM::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  77. {
  78. bool unknowns = false;
  79. for (unsigned int i = 0;i != cNames;i++)
  80. {
  81. CHECK_ID("Idle", DISP_APPLICATION_IDLE)
  82. CHECK_ID("GetLanguage", DISP_APPLICATION_GETLANGUAGE)
  83. CHECK_ID("IsWinampPro", DISP_APPLICATION_ISWINAMPPRO)
  84. CHECK_ID("GetCountry", DISP_APPLICATION_GETCOUNTRY)
  85. CHECK_ID("GetLocale", DISP_APPLICATION_GETLOCALE)
  86. CHECK_ID("LaunchURL", DISP_APPLICATION_LAUNCHURL)
  87. CHECK_ID("Version", DISP_APPLICATION_VERSION)
  88. CHECK_ID("GetSpecialBuildName", DISP_APPLICATION_SPECIALBUILD)
  89. CHECK_ID("DownloadMedia", DISP_APPLICATION_DOWNLOADMEDIA)
  90. CHECK_ID("CreateTempFile", DISP_APPLICATION_CREATETEMPFILE)
  91. rgdispid[i] = DISPID_UNKNOWN;
  92. unknowns = true;
  93. }
  94. if (unknowns)
  95. return DISP_E_UNKNOWNNAME;
  96. else
  97. return S_OK;
  98. }
  99. HRESULT ApplicationCOM::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  100. {
  101. return E_NOTIMPL;
  102. }
  103. HRESULT ApplicationCOM::GetTypeInfoCount(unsigned int FAR * pctinfo)
  104. {
  105. return E_NOTIMPL;
  106. }
  107. void GetLanguage(wchar_t *language, size_t size)
  108. {
  109. StringCchCopyW(language, size, WASABI_API_LNG->GetLanguageIdentifier(LANG_LANG_CODE));
  110. }
  111. void GetCountry(wchar_t *language, size_t size)
  112. {
  113. // language packs aren't country-specific enough to use them for country info, yet
  114. int err = GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME , language, (int)size);
  115. if (err == 0) // win95 doesn't support this flag, so we'll check for an error
  116. lstrcpynW(language, L"US", (int)size); // and default to english
  117. }
  118. void CALLBACK OpenURLAPC(ULONG_PTR param)
  119. {
  120. wchar_t *url = (wchar_t *)param;
  121. myOpenURL(NULL, url);
  122. free(url);
  123. }
  124. void GetPathToStore(wchar_t path_to_store[MAX_PATH])
  125. {
  126. if (FAILED(SHGetFolderPathW(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, path_to_store)))
  127. {
  128. if (FAILED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path_to_store)))
  129. {
  130. // and if that all fails then do a reasonable default
  131. GetPrivateProfileStringW(L"gen_ml_config", L"extractpath", L"C:\\My Music", path_to_store, MAX_PATH, ML_INI_FILE);
  132. }
  133. // if there's no valid My Music folder (typically win2k) then default to %my_documents%\my music
  134. else
  135. {
  136. PathCombineW(path_to_store, path_to_store, L"My Music");
  137. }
  138. }
  139. }
  140. static void CALLBACK SendOpenUrl_Callback(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
  141. {
  142. if (NULL != dwData)
  143. free((void*)dwData);
  144. }
  145. HRESULT ApplicationCOM::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  146. {
  147. switch (dispid)
  148. {
  149. case DISP_APPLICATION_CREATETEMPFILE:
  150. {
  151. IDispatch *tempFile =0;
  152. if (pdispparams->cArgs == 1)
  153. tempFile = new TempFileCOM(pdispparams->rgvarg[0].bstrVal);
  154. else
  155. tempFile = new TempFileCOM(0);
  156. VariantInit(pvarResult);
  157. V_VT(pvarResult) = VT_DISPATCH;
  158. V_DISPATCH(pvarResult) = tempFile;
  159. return S_OK;
  160. }
  161. case DISP_APPLICATION_DOWNLOADMEDIA:
  162. {
  163. const wchar_t *url = pdispparams->rgvarg[0].bstrVal;
  164. if (url)
  165. {
  166. const wchar_t *destFileSpec=PathFindFileNameW(url);
  167. wchar_t path_to_store[MAX_PATH] = {0};
  168. GetPathToStore(path_to_store);
  169. wchar_t destfile[MAX_PATH] = {0};
  170. wchar_t dlgtitle[256] = {0};
  171. CreateDirectoryW(path_to_store, NULL);
  172. PathCombineW(destfile, path_to_store, destFileSpec);
  173. httpRetrieveFileW(hMainWindow, AutoChar(url), destfile, getStringW(IDS_DOWNLOADING, dlgtitle,256));
  174. LMDB_FILE_ADD_INFOW fi = {const_cast<wchar_t *>(destfile), -1, -1};
  175. sendMlIpc(ML_IPC_DB_ADDORUPDATEFILEW, (WPARAM)&fi);
  176. sendMlIpc(ML_IPC_DB_SYNCDB, 0);
  177. }
  178. }
  179. return S_OK;
  180. case DISP_APPLICATION_IDLE:
  181. //Idle();
  182. return S_OK;
  183. case DISP_APPLICATION_GETLANGUAGE:
  184. {
  185. wchar_t langName[8] = {0};
  186. GetLanguage(langName, 8);
  187. BSTR language = SysAllocString(langName);
  188. VariantInit(pvarResult);
  189. V_VT(pvarResult) = VT_BSTR;
  190. V_BSTR(pvarResult) = language;
  191. return S_OK;
  192. }
  193. case DISP_APPLICATION_GETCOUNTRY:
  194. {
  195. wchar_t countryName[8] = {0};
  196. GetCountry(countryName, 8);
  197. BSTR country = SysAllocString(countryName);
  198. VariantInit(pvarResult);
  199. V_VT(pvarResult) = VT_BSTR;
  200. V_BSTR(pvarResult) = country;
  201. return S_OK;
  202. }
  203. case DISP_APPLICATION_GETLOCALE:
  204. {
  205. wchar_t countryName[8] = {0};
  206. GetCountry(countryName, 8);
  207. wchar_t langName[8] = {0};
  208. GetLanguage(langName, 8);
  209. wchar_t language_country[16] = {0};
  210. StringCchPrintfW(language_country, 16, L"%s-%s", langName, countryName);
  211. BSTR languageAndCountryCode = SysAllocString(language_country);
  212. VariantInit(pvarResult);
  213. V_VT(pvarResult) = VT_BSTR;
  214. V_BSTR(pvarResult) = languageAndCountryCode;
  215. return S_OK;
  216. }
  217. case DISP_APPLICATION_ISWINAMPPRO:
  218. {
  219. VariantInit(pvarResult);
  220. V_VT(pvarResult) = VT_BOOL;
  221. V_BOOL(pvarResult) = VARIANT_TRUE;
  222. return S_OK;
  223. }
  224. case DISP_APPLICATION_LAUNCHURL:
  225. if (pdispparams->cArgs == 1 || pdispparams->cArgs == 2)
  226. {
  227. if (JSAPI_PARAM_OPTIONAL(pdispparams, 2, boolVal, FALSE) == TRUE)
  228. ShellExecuteW(NULL, L"open", JSAPI_PARAM(pdispparams, 1).bstrVal, NULL, L".", 0);
  229. else
  230. {
  231. LPWSTR url = _wcsdup(JSAPI_PARAM(pdispparams, 1).bstrVal);
  232. if ( 0 == SendMessageCallback(hMainWindow, WM_WA_IPC, (WPARAM)url, (LPARAM)IPC_OPEN_URL, SendOpenUrl_Callback, (ULONG_PTR)url) &&
  233. 0 == QueueUserAPC(OpenURLAPC, hMainThread, (ULONG_PTR)url))
  234. {
  235. free(url);
  236. }
  237. }
  238. return S_OK;
  239. }
  240. else
  241. return DISP_E_BADPARAMCOUNT;
  242. case DISP_APPLICATION_VERSION:
  243. {
  244. AutoWide versionW(APP_VERSION);
  245. BSTR versionB = SysAllocString(versionW);
  246. VariantInit(pvarResult);
  247. V_VT(pvarResult) = VT_BSTR;
  248. V_BSTR(pvarResult) = versionB;
  249. return S_OK;
  250. }
  251. case DISP_APPLICATION_SPECIALBUILD:
  252. {
  253. BSTR special = SysAllocString(SPECIAL_BUILD_NAME);
  254. VariantInit(pvarResult);
  255. V_VT(pvarResult) = VT_BSTR;
  256. V_BSTR(pvarResult) = special;
  257. return S_OK;
  258. }
  259. }
  260. return DISP_E_MEMBERNOTFOUND;
  261. }
  262. STDMETHODIMP ApplicationCOM::QueryInterface(REFIID riid, PVOID *ppvObject)
  263. {
  264. if (!ppvObject)
  265. return E_POINTER;
  266. else if (IsEqualIID(riid, IID_IDispatch))
  267. *ppvObject = (IDispatch *)this;
  268. else if (IsEqualIID(riid, IID_IUnknown))
  269. *ppvObject = this;
  270. else
  271. {
  272. *ppvObject = NULL;
  273. return E_NOINTERFACE;
  274. }
  275. AddRef();
  276. return S_OK;
  277. }
  278. ULONG ApplicationCOM::AddRef(void)
  279. {
  280. return 0;
  281. }
  282. ULONG ApplicationCOM::Release(void)
  283. {
  284. return 0;
  285. }
  286. void ApplicationCOM::Idle()
  287. {
  288. WASABI_API_APP->app_messageLoopStep();
  289. }