diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/omBrowser/main.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/omBrowser/main.cpp')
-rw-r--r-- | Src/omBrowser/main.cpp | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/Src/omBrowser/main.cpp b/Src/omBrowser/main.cpp new file mode 100644 index 00000000..693e0890 --- /dev/null +++ b/Src/omBrowser/main.cpp @@ -0,0 +1,662 @@ +#include "./main.h" +#include "./component.h" +#include "../nu/htmlcontainer2.h" +#include "./ifc_wasabihelper.h" +#include "./ifc_skinhelper.h" +#include "./ifc_skinnedbrowser.h" +#include "./pngLoader.h" +#include "./ifc_omservicehost.h" + +#include <shlwapi.h> +#include <strsafe.h> + +static HINSTANCE pluginInstance = NULL; +static OmBrowserComponent component; + +LPWSTR Plugin_MallocString(size_t cchLen) +{ + return (LPWSTR)calloc(cchLen, sizeof(WCHAR)); +} + +void Plugin_FreeString(LPWSTR pszString) +{ + if (NULL != pszString) + { + free(pszString); + } +} + +LPWSTR Plugin_ReAllocString(LPWSTR pszString, size_t cchLen) +{ + return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen); +} + +LPWSTR Plugin_CopyString(LPCWSTR pszSource) +{ + if (NULL == pszSource) + return NULL; + + INT cchSource = lstrlenW(pszSource) + 1; + + LPWSTR copy = Plugin_MallocString(cchSource); + if (NULL != copy) + { + CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource); + } + return copy; +} + +LPSTR Plugin_MallocAnsiString(size_t cchLen) +{ + return (LPSTR)calloc(cchLen, sizeof(CHAR)); +} + +LPSTR Plugin_CopyAnsiString(LPCSTR pszSource) +{ + if (NULL == pszSource) + return NULL; + + INT cchSource = lstrlenA(pszSource) + 1; + + LPSTR copy = Plugin_MallocAnsiString(cchSource); + if (NULL != copy) + { + CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource); + } + return copy; +} + +void Plugin_FreeAnsiString(LPSTR pszString) +{ + Plugin_FreeString((LPWSTR)pszString); +} + +LPWSTR Plugin_DuplicateResString(LPCWSTR pszResource) +{ + return (IS_INTRESOURCE(pszResource)) ? + (LPWSTR)pszResource : + Plugin_CopyString(pszResource); +} + +void Plugin_FreeResString(LPWSTR pszResource) +{ + if (!IS_INTRESOURCE(pszResource)) + Plugin_FreeString(pszResource); +} + +HRESULT Plugin_CopyResString(LPWSTR pszBuffer, INT cchBufferMax, LPCWSTR pszString) +{ + if (NULL == pszBuffer) + return E_INVALIDARG; + + HRESULT hr = S_OK; + + if (NULL == pszString) + { + pszBuffer[0] = L'\0'; + } + else if (IS_INTRESOURCE(pszString)) + { + Plugin_LoadString((INT)(INT_PTR)pszString, pszBuffer, cchBufferMax); + } + else + { + hr = StringCchCopy(pszBuffer, cchBufferMax, pszString); + } + return hr; +} + +LPSTR Plugin_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) +{ + INT cchBuffer = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar); + if (0 == cchBuffer) return NULL; + + LPSTR buffer = Plugin_MallocAnsiString(cchBuffer); + if (NULL == buffer) return NULL; + + if (0 == WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, buffer, cchBuffer, lpDefaultChar, lpUsedDefaultChar)) + { + Plugin_FreeAnsiString(buffer); + return NULL; + } + return buffer; +} + +LPWSTR Plugin_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte) +{ + if (NULL == lpMultiByteStr) return NULL; + INT cchBuffer = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0); + if (NULL == cchBuffer) return NULL; + + if (cbMultiByte > 0) cchBuffer++; + + LPWSTR buffer = Plugin_MallocString(cchBuffer); + if (NULL == buffer) return NULL; + + if (0 == MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, buffer, cchBuffer)) + { + Plugin_FreeString(buffer); + return NULL; + } + + if (cbMultiByte > 0) + { + buffer[cchBuffer - 1] = L'\0'; + } + return buffer; +} + +HRESULT Plugin_Initialize(HWND hwndWinamp) +{ + return component.InitializeComponent(hwndWinamp); +} + +HRESULT Plugin_GetWasabiHelper(ifc_wasabihelper **wasabiHelper) +{ + return component.GetWasabiHelper(wasabiHelper); +} + +HRESULT Plugin_GetSkinHelper(ifc_skinhelper **skinHelper) +{ + return component.GetSkinHelper(skinHelper); +} + +HRESULT Plugin_GetBrowserSkin(ifc_skinnedbrowser **skinnedBrowser) +{ + ifc_skinhelper *skin = NULL; + HRESULT hr = Plugin_GetSkinHelper(&skin); + if (FAILED(hr) || skin == NULL) return hr; + + hr = skin->QueryInterface(IFC_SkinnedBrowser, (void**)skinnedBrowser); + skin->Release(); + return hr; +} + +HRESULT Plugin_GetWinampWnd(HWND *hwndWinamp) +{ + return component.GetWinampWnd(hwndWinamp); +} + + +HRESULT Plugin_RegisterWinampHook(ifc_winamphook *hook, UINT *cookieOut) +{ + return component.RegisterWinampHook(hook, cookieOut); +} + +HRESULT Plugin_UnregisterWinampHook(UINT cookie) +{ + return component.UnregisterWinampHook(cookie); +} + + +HINSTANCE Plugin_GetInstance() +{ + return pluginInstance; +} + +HINSTANCE Plugin_GetLangInstance() +{ + ifc_wasabihelper *wasabi = NULL; + if (FAILED(component.GetWasabiHelper(&wasabi)) || wasabi == NULL) return NULL; + + HINSTANCE langModule = NULL; + if (FAILED(wasabi->GetLanguageModule(&langModule))) + langModule = NULL; + + wasabi->Release(); + return langModule; +} + +HRESULT Plugin_FormatUuidString(UUID &uid, LPWSTR pszBuffer, size_t cchBufferMax) +{ + if (NULL == pszBuffer || cchBufferMax < 1) + return E_INVALIDARG; + + pszBuffer[0] = L'\0'; + + RPC_WSTR pszUid; + if (RPC_S_OK != UuidToString(&uid, &pszUid)) + { + DWORD errorCode = GetLastError(); + return HRESULT_FROM_WIN32(errorCode); + } + + UINT cchLen = lstrlen((LPCWSTR)pszUid); + UINT s = 0, d = 0; + + for (; s < cchLen && d < cchBufferMax; s++) + { + if (pszUid[s] >= L'a' && pszUid[s] <= L'f') + { + pszBuffer[d++] = (0xDF & pszUid[s]); + } + else if (pszUid[s] >= L'0' && pszUid[s] <= L'9') + { + pszBuffer[d++] = pszUid[s]; + } + } + + if (d > cchBufferMax) + d = 0; + + pszBuffer[d] = L'\0'; + RpcStringFree(&pszUid); + + return (L'\0' != pszBuffer[0]) ? S_OK : E_FAIL; +} + +static HINSTANCE Plugin_GetLangHelper(api_language **langManager) +{ + ifc_wasabihelper *wasabi = NULL; + if (FAILED(component.GetWasabiHelper(&wasabi)) || wasabi == NULL) + { + *langManager = NULL; + return NULL; + } + + if (FAILED(wasabi->GetLanguageManager(langManager))) + *langManager = NULL; + + HINSTANCE langModule = NULL; + if (FAILED(wasabi->GetLanguageModule(&langModule))) + langModule = NULL; + + wasabi->Release(); + + return langModule; +} + +const wchar_t* Plugin_LoadString(UINT id, wchar_t *buffer, int bufferMax) +{ + const wchar_t* r = 0; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->GetStringW(langModule, Plugin_GetInstance(), id, buffer, bufferMax); + lang->Release(); + } + return r; +} + +const char* Plugin_LoadStringAnsi(UINT id, char *buffer, int bufferMax) +{ + const char* r = 0; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->GetString(langModule, Plugin_GetInstance(), id, buffer, bufferMax); + lang->Release(); + } + return r; +} + +HWND Plugin_CreateDialogParam(const wchar_t *templateName, HWND parent, DLGPROC proc, LPARAM param) +{ + HWND r = 0; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->CreateLDialogParamW(langModule, Plugin_GetInstance(), (INT)(INT_PTR)templateName, parent, proc, param); + lang->Release(); + } + return r; +} + +INT_PTR Plugin_DialogBoxParam(const wchar_t *templateName, HWND parent, DLGPROC proc, LPARAM param) +{ + INT_PTR r = -1; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->LDialogBoxParamW(langModule, Plugin_GetInstance(), (INT)(INT_PTR)templateName, parent, proc, param); + lang->Release(); + } + return r; +} + +HMENU Plugin_LoadMenu(const wchar_t *menuName) +{ + HMENU r = NULL; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->LoadLMenuW(langModule, Plugin_GetInstance(), (INT)(INT_PTR)menuName); + lang->Release(); + } + return r; +} + +void *Plugin_LoadResource(const wchar_t *resourceType, const wchar_t *resourceName, unsigned long *size) +{ + void *r = NULL; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->LoadResourceFromFileW(langModule, Plugin_GetInstance(), resourceType, resourceName, size); + lang->Release(); + } + return r; +} + +HACCEL Plugin_LoadAccelerators(const wchar_t *tableName) +{ + HACCEL r = NULL; + api_language *lang = NULL; + HINSTANCE langModule = Plugin_GetLangHelper(&lang); + if (NULL != lang) + { + r = lang->LoadAcceleratorsW(langModule, Plugin_GetInstance(), tableName); + lang->Release(); + } + return r; +} + +HRESULT Plugin_QueryImageLoader(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, ifc_omimageloader **imageLoader) +{ + if (NULL == imageLoader) return E_POINTER; + *imageLoader = NULL; + + if (NULL == pszName) return E_INVALIDARG; + + return PngLoader::CreateInstance(hInstance, pszName, fPremultiply, imageLoader); +} + +size_t Plugin_TlsAlloc(void) +{ + size_t index = TLS_OUT_OF_INDEXES; + ifc_wasabihelper *wasabi = NULL; + if (SUCCEEDED(component.GetWasabiHelper(&wasabi)) && wasabi != NULL) + { + api_application *app = NULL; + if (SUCCEEDED(wasabi->GetApplicationApi(&app)) && app != NULL) + { + index = app->AllocateThreadStorage(); + app->Release(); + } + } + return index; +} + +BOOL Plugin_TlsFree(size_t index) +{ + return FALSE; +} + +void *Plugin_TlsGetValue(size_t index) +{ + void *result = NULL; + ifc_wasabihelper *wasabi = NULL; + if (SUCCEEDED(component.GetWasabiHelper(&wasabi)) && wasabi != NULL) + { + api_application *app = NULL; + if (SUCCEEDED(wasabi->GetApplicationApi(&app)) && app != NULL) + { + result = app->GetThreadStorage(index); + app->Release(); + } + } + return result; +} + +BOOL Plugin_TlsSetValue(size_t index, void* value) +{ + BOOL result = FALSE; + ifc_wasabihelper *wasabi = NULL; + if (SUCCEEDED(component.GetWasabiHelper(&wasabi)) && wasabi != NULL) + { + api_application *app = NULL; + if (SUCCEEDED(wasabi->GetApplicationApi(&app)) && app != NULL) + { + app->SetThreadStorage(index, value); + app->Release(); + result = TRUE; + } + } + return result; +} + +void Plugin_RegisterUnloadCallback(PLUGINUNLOADCALLBACK callback) +{ + component.RegisterUnloadCallback(callback); +} + +HRESULT Plugin_GetBrowserClass(LPCWSTR pszName, ifc_ombrowserclass **instance) +{ + return component.GetBrowserClass(pszName, instance); +} + +HRESULT Plugin_UnregisterBrowserClass(LPCWSTR pszName) +{ + return component.UnregisterBrowserClass(pszName); +} + +HRESULT Plugin_EnsurePathExist(LPCWSTR pszDirectory) +{ + DWORD ec = ERROR_SUCCESS; + UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); + + if (0 == CreateDirectory(pszDirectory, NULL)) + { + ec = GetLastError(); + if (ERROR_PATH_NOT_FOUND == ec) + { + LPCWSTR pszBlock = pszDirectory; + WCHAR szBuffer[MAX_PATH] = {0}; + + LPCTSTR pszCursor = PathFindNextComponent(pszBlock); + ec = (pszCursor == pszBlock || S_OK != StringCchCopyN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock))) ? + ERROR_INVALID_NAME : ERROR_SUCCESS; + + pszBlock = pszCursor; + + while (ERROR_SUCCESS == ec && NULL != (pszCursor = PathFindNextComponent(pszBlock))) + { + if (pszCursor == pszBlock || S_OK != StringCchCatN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock))) + ec = ERROR_INVALID_NAME; + + if (ERROR_SUCCESS == ec && !CreateDirectory(szBuffer, NULL)) + { + ec = GetLastError(); + if (ERROR_ALREADY_EXISTS == ec) ec = ERROR_SUCCESS; + } + pszBlock = pszCursor; + } + } + + if (ERROR_ALREADY_EXISTS == ec) + ec = ERROR_SUCCESS; + } + + SetErrorMode(errorMode); + SetLastError(ec); + return HRESULT_FROM_WIN32(ec); +} + +HRESULT Plugin_MakeResourcePath(LPWSTR pszBuffer, UINT cchBufferMax, HINSTANCE hInstance, LPCWSTR pszType, LPCWSTR pszName, UINT uFlags) +{ + if (NULL == pszBuffer) return E_INVALIDARG; + + if (NULL == hInstance || NULL == pszName) + { + pszBuffer[0] = L'\0'; + return E_INVALIDARG; + } + + LPWSTR cursor = pszBuffer; + size_t remaining = cchBufferMax; + + HRESULT hr = StringCchCopyEx(cursor, remaining, L"res://", &cursor, &remaining, 0); + if (SUCCEEDED(hr)) + { + DWORD cchPath = GetModuleFileName(hInstance, cursor, (DWORD)remaining); + if (0 == cchPath) + { + DWORD errorCode = GetLastError(); + hr = HRESULT_FROM_WIN32(errorCode); + } + else + { + if (0 != (RESPATH_COMPACT & uFlags)) + { + ifc_wasabihelper *wasabi = NULL; + if (SUCCEEDED(Plugin_GetWasabiHelper(&wasabi)) && wasabi != NULL) + { + api_application *application = NULL; + if (SUCCEEDED(wasabi->GetApplicationApi(&application)) && application != NULL) + { + WCHAR szPlugin[MAX_PATH] = {0}; + HINSTANCE hWinamp = application->main_gethInstance(); + if (NULL != hWinamp && 0 != GetModuleFileName(hWinamp, szPlugin, ARRAYSIZE(szPlugin))) + { + PathRemoveFileSpec(szPlugin); + INT cchCommon = PathCommonPrefix(cursor, szPlugin, NULL); + // prevents messing things up if on same drive and that's all that matches + if (cchCommon > 3) + { + cchCommon++; + cchPath -= cchCommon; + MoveMemory(cursor, cursor + cchCommon, cchPath * sizeof(WCHAR)); + cursor[cchPath] = L'\0'; + } + } + application->Release(); + } + wasabi->Release(); + } + } + + remaining -= cchPath; + cursor += cchPath; + } + + LPCWSTR pszTemplate = NULL; + if (SUCCEEDED(hr) && NULL != pszType) + { + if (IS_INTRESOURCE(pszType)) + { + pszTemplate = (0 != (RESPATH_TARGETIE & uFlags)) ? L"/%d" : L"/#%d"; + hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, 0, pszTemplate, pszType); + } + else if (L'\0' != *pszType) + { + hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, 0, L"/%s", pszType); + } + } + + if (SUCCEEDED(hr)) + { + if (IS_INTRESOURCE(pszName)) + pszTemplate = (0 != (RESPATH_TARGETIE & uFlags)) ? L"/%d" : L"/#%d"; + else + pszTemplate = L"/%s"; + + hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, 0, pszTemplate, pszName); + } + } + + if (FAILED(hr)) + pszBuffer[0] = L'\0'; + + return hr; +} + +HRESULT Plugin_ResolveRelativePath(LPCWSTR pszPath, ifc_omservicehost *host, LPWSTR pszBuffer, UINT cchBufferMax) +{ + if (NULL == pszBuffer) + return E_POINTER; + + HRESULT hr = S_OK; + + if (NULL != pszPath && L'\0' == *pszPath) + pszPath = NULL; + + if (NULL != pszPath && FALSE == PathIsRelative(pszPath)) + { + hr = StringCchCopy(pszBuffer, cchBufferMax, pszPath); + return (FAILED(hr)) ? hr : S_FALSE; + } + + WCHAR szBase[MAX_PATH] = {0}; + if (NULL == host || FAILED(host->GetBasePath(NULL, szBase, ARRAYSIZE(szBase)))) + szBase[0]= L'\0'; + + if (L'\0' == szBase[0] || PathIsRelative(szBase)) + { + ifc_wasabihelper *wasabi = NULL; + if (SUCCEEDED(Plugin_GetWasabiHelper(&wasabi)) && wasabi != NULL) + { + api_application *application = NULL; + if (SUCCEEDED(wasabi->GetApplicationApi(&application)) && application != NULL) + { + LPCWSTR pszUser = application->path_getUserSettingsPath(); + if (NULL != pszUser && L'\0' != *pszUser) + { + if (L'\0' != szBase[0]) + hr = StringCchCopy(pszBuffer, cchBufferMax, szBase); + + if (SUCCEEDED(hr)) + { + hr = StringCchCopy(szBase, ARRAYSIZE(szBase), pszUser); + if (SUCCEEDED(hr) && L'\0' != *pszBuffer && FALSE == PathAppend(szBase, pszBuffer)) + hr = E_OUTOFMEMORY; + } + } + application->Release(); + } + wasabi->Release(); + } + } + + if (SUCCEEDED(hr) && NULL != pszPath) + { + if (L'\0' == szBase[0]) + hr = StringCchCopy(szBase, ARRAYSIZE(szBase), pszPath); + else if (FALSE == PathAppend(szBase, pszPath)) + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr) && 0 == PathCanonicalize(pszBuffer, szBase)) + hr = E_OUTOFMEMORY; + + return hr; +} + +BOOL Plugin_IsDirectMouseWheelMessage(const UINT uMsg) +{ + static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL; + + if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL) + { + WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL"); + if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL) + return FALSE; + } + + return (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg); +} + +extern "C" __declspec(dllexport) ifc_wa5component *GetWinamp5SystemComponent() +{ + return &component; +} + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD uReason, void *reserved) +{ + switch(uReason) + { + case DLL_PROCESS_ATTACH: + pluginInstance = (HINSTANCE)hModule; + HTMLContainer2_Initialize(); + break; + case DLL_PROCESS_DETACH: + HTMLContainer2_Uninitialize(); + break; + } + return TRUE; +}
\ No newline at end of file |