#include "main.h" #include "./serviceHost.h" #include "./api__ml_online.h" #include "./resource.h" #include "./external.h" #include "./navigation.h" #include "./commands.h" #include "./serviceHelper.h" #include #include #include #include #include #include #include "../winamp/IWasabiDispatchable.h" #include "../winamp/JSAPI_Info.h" #include #include #define IS_INVALIDISPATCH(__disp) (((IDispatch *)1) == (__disp) || NULL == (__disp)) static ServiceHost *cachedInstance = NULL; static void CALLBACK StorageHandler_ReadAuth(ifc_omservice *service, LPCWSTR pszKey, LPCWSTR pszValue) { INT iVal; UINT flags = (NULL != pszValue && FALSE != StrToIntEx(pszValue, STIF_SUPPORT_HEX, &iVal) && 0 != iVal) ? SVCF_USECLIENTOWEB : 0; ServiceHelper_SetFlags(service, flags, SVCF_USECLIENTOWEB); } static void CALLBACK StorageHandler_ReadBypass(ifc_omservice *service, LPCWSTR pszKey, LPCWSTR pszValue) { INT iVal; UINT flags = (NULL != pszValue && FALSE != StrToIntEx(pszValue, STIF_SUPPORT_HEX, &iVal) && 0 != iVal) ? SVCF_PREAUTHORIZED : 0; ServiceHelper_SetFlags(service, flags, SVCF_PREAUTHORIZED); } static void CALLBACK StorageHandler_ReadSubscribed(ifc_omservice *service, LPCWSTR pszKey, LPCWSTR pszValue) { INT iVal; UINT flags = (NULL != pszValue && FALSE != StrToIntEx(pszValue, STIF_SUPPORT_HEX, &iVal) && 0 != iVal) ? SVCF_SUBSCRIBED : 0; flags |= SVCF_AUTOUPGRADE; ServiceHelper_SetFlags(service, flags, SVCF_SUBSCRIBED | SVCF_AUTOUPGRADE); } static const ifc_omstoragehelper::TemplateRecord szStorageExtXml[] = { { L"auth", StorageHandler_ReadAuth }, { L"bypass", StorageHandler_ReadBypass }, }; static const ifc_omstoragehelper::TemplateRecord szStorageExtIni[] = { { L"subscribed", StorageHandler_ReadSubscribed }, }; ServiceHost::ServiceHost() : ref(1), storageExtXml(NULL), storageExtIni(NULL) { } ServiceHost::~ServiceHost() { if (NULL != storageExtXml) storageExtXml->Release(); if (NULL != storageExtIni) storageExtIni->Release(); } HRESULT ServiceHost::CreateInstance(ServiceHost **instance) { if (NULL == instance) return E_POINTER; *instance = new ServiceHost(); if (NULL == instance) return E_OUTOFMEMORY; return S_OK; } HRESULT ServiceHost::GetCachedInstance(ServiceHost **instance) { if (NULL == instance) return E_POINTER; if (NULL == cachedInstance) { HRESULT hr = CreateInstance(&cachedInstance); if (FAILED(hr)) { *instance = NULL; return hr; } } cachedInstance->AddRef(); *instance = cachedInstance; return S_OK; } HRESULT ServiceHost::ReleseCache() { if (NULL == cachedInstance) return S_FALSE; ServiceHost *t = cachedInstance; cachedInstance = NULL; t->Release(); return S_OK; } size_t ServiceHost::AddRef() { return InterlockedIncrement((LONG*)&ref); } size_t ServiceHost::Release() { if (0 == ref) return ref; LONG r = InterlockedDecrement((LONG*)&ref); if (0 == r) delete(this); return r; } int ServiceHost::QueryInterface(GUID interface_guid, void **object) { if (NULL == object) return E_POINTER; if (IsEqualIID(interface_guid, IFC_OmServiceHost)) *object = static_cast(this); else if (IsEqualIID(interface_guid, IFC_OmServiceEvent)) *object = static_cast(this); else if (IsEqualIID(interface_guid, IFC_OmStorageExt)) *object = static_cast(this); else { *object = NULL; return E_NOINTERFACE; } if (NULL == *object) return E_UNEXPECTED; AddRef(); return S_OK; } HRESULT ServiceHost::GetExternal(ifc_omservice *service, IDispatch **ppDispatch) { if (NULL == ppDispatch) return E_POINTER; if (NULL != *ppDispatch) { // try to connect our external IWasabiDispatchable *pWasabi; if (SUCCEEDED((*ppDispatch)->QueryInterface(IID_IWasabiDispatchable, (void**)&pWasabi))) { JSAPI::ifc_info *pInfo; if (SUCCEEDED(pWasabi->QueryDispatchable(JSAPI::IID_JSAPI_ifc_info, (Dispatchable**)&pInfo))) { ExternalDispatch *pExternal; if (SUCCEEDED(ExternalDispatch::CreateInstance(&pExternal))) { pInfo->AddAPI(pExternal->GetName(), pExternal); pExternal->Release(); } pInfo->Release(); } pWasabi->Release(); } } return S_OK; } HRESULT ServiceHost::GetBasePath(ifc_omservice *service, LPWSTR pszBuffer, UINT cchBufferMax) { if (NULL == pszBuffer) return E_POINTER; return StringCchCopy(pszBuffer, cchBufferMax, L".\\Plugins\\ml\\omServices"); } HRESULT ServiceHost::GetDefaultName(ifc_omservice *service, LPWSTR pszBuffer, UINT cchBufferMax) { if (NULL == pszBuffer) return E_POINTER; if (NULL == service) return E_INVALIDARG; return StringCchPrintf(pszBuffer, cchBufferMax, L"omService_{%010u}.ini", service->GetId()); } HRESULT ServiceHost::QueryCommandState(ifc_omservice *service, HWND hBrowser, const GUID *commandGroup, UINT commandId) { if (NULL == service || NULL == commandGroup) return E_NOTIMPL; if (IsEqualGUID(*commandGroup, CMDGROUP_SERVICE)) { switch(commandId) { case SVCCOMMAND_SHOWINFO: case SVCCOMMAND_REPORT: case SVCCOMMAND_UNSUBSCRIBE: case SVCCOMMAND_RATE: if (S_FALSE == ServiceHelper_IsSpecial(service)) { return CMDSTATE_ENABLED; } return CMDSTATE_UNKNOWN; case SVCCOMMAND_BLOCKNAV: { UINT flags; if (FAILED(service->GetFlags(&flags))) flags = 0; HRESULT state = (0 == (SVCF_VERSIONCHECK & flags)) ? CMDSTATE_DISABLED : CMDSTATE_ENABLED; ServiceHelper_UpdateOperationInfo(hBrowser); return state; } break; } } return E_NOTIMPL; } HRESULT ServiceHost::ExecuteCommand(ifc_omservice *service, HWND hBrowser, const GUID *commandGroup, UINT commandId, ULONG_PTR commandArg) { if (IsEqualGUID(CMDGROUP_SERVICE, *commandGroup)) { if (S_OK != ServiceHelper_IsSpecial(service)) { switch(commandId) { case SVCCOMMAND_SHOWINFO: Command_ShowServiceInfo(service); return S_OK; case SVCCOMMAND_REPORT: Command_ReportService(service); return S_OK; case SVCCOMMAND_UNSUBSCRIBE: Command_UnsubscribeService(service); return S_OK; case SVCCOMMAND_RATE: Command_SetServiceRating(service, (UINT)commandArg); return S_OK; } } } return E_NOTIMPL; } void ServiceHost::ServiceChange(ifc_omservice *service, UINT nModified) { if (NULL == service) return; Navigation *navigation; if (SUCCEEDED(Plugin_GetNavigation(&navigation))) { navigation->UpdateService(service, nModified); navigation->Release(); } } HRESULT ServiceHost::EnumerateStorageExt(const GUID *storageId, ifc_omstoragehandlerenum **enumerator) { if (NULL == storageId) return E_INVALIDARG; if (IsEqualGUID(SUID_OmStorageXml, *storageId)) { if (NULL == storageExtXml) { ifc_omstoragehelper *storageHelper; if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetStorageHelper(&storageHelper))) { if (FAILED(storageHelper->CreateEnumerator(szStorageExtXml, ARRAYSIZE(szStorageExtXml), &storageExtXml))) storageExtXml = NULL; storageHelper->Release(); } if (NULL == storageExtXml) return E_FAIL; } *enumerator = storageExtXml; storageExtXml->AddRef(); return S_OK; } else if (IsEqualGUID(SUID_OmStorageIni, *storageId)) { if (NULL == storageExtIni) { ifc_omstoragehelper *storageHelper; if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetStorageHelper(&storageHelper))) { if (FAILED(storageHelper->CreateEnumerator(szStorageExtIni, ARRAYSIZE(szStorageExtIni), &storageExtIni))) storageExtIni = NULL; storageHelper->Release(); } if (NULL == storageExtIni) return E_FAIL; } *enumerator = storageExtIni; storageExtIni->AddRef(); return S_OK; } return E_NOTIMPL; } HRESULT ServiceHost::GetUrl(ifc_omservice *service, LPWSTR pszBuffer, UINT cchBufferMax) { UINT flags; if (NULL != service && SUCCEEDED(service->GetFlags(&flags)) && 0 != (SVCF_USECLIENTOWEB & flags) && NULL != AGAVE_API_AUTH) { LPWSTR pszUrl = Plugin_CopyString(pszBuffer); if (NULL == pszUrl) return E_OUTOFMEMORY; HRESULT hr(E_NOTIMPL); if (0 == AGAVE_API_AUTH->ClientToWeb(GUID_NULL, pszUrl, pszBuffer, cchBufferMax)) hr = S_OK; Plugin_FreeString(pszUrl); return hr; } return E_NOTIMPL; } #define CBCLASS ServiceHost START_MULTIPATCH; START_PATCH(MPIID_OMSVCHOST) M_CB(MPIID_OMSVCHOST, ifc_omservicehost, ADDREF, AddRef); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, RELEASE, Release); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, QUERYINTERFACE, QueryInterface); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_GETEXTERNAL, GetExternal); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_GETBASEPATH, GetBasePath); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_GETDEFAULTNAME, GetDefaultName); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_QUERYCOMMANDSTATE, QueryCommandState); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_EXECUTECOMMAND, ExecuteCommand); M_CB(MPIID_OMSVCHOST, ifc_omservicehost, API_GETURL, GetUrl); NEXT_PATCH(MPIID_OMSVCEVENT) M_CB(MPIID_OMSVCEVENT, ifc_omserviceevent, ADDREF, AddRef); M_CB(MPIID_OMSVCEVENT, ifc_omserviceevent, RELEASE, Release); M_CB(MPIID_OMSVCEVENT, ifc_omserviceevent, QUERYINTERFACE, QueryInterface); M_VCB(MPIID_OMSVCEVENT, ifc_omserviceevent, API_SERVICECHANGE, ServiceChange); NEXT_PATCH(MPIID_OMSTRGEXT) M_CB(MPIID_OMSTRGEXT, ifc_omstorageext, ADDREF, AddRef); M_CB(MPIID_OMSTRGEXT, ifc_omstorageext, RELEASE, Release); M_CB(MPIID_OMSTRGEXT, ifc_omstorageext, QUERYINTERFACE, QueryInterface); M_CB(MPIID_OMSTRGEXT, ifc_omstorageext, API_ENUMERATE, EnumerateStorageExt); END_PATCH END_MULTIPATCH; #undef CBCLASS