winamp/Src/auth/Loginbox/common.cpp

618 lines
14 KiB
C++
Raw Normal View History

2024-09-24 12:54:57 +00:00
#include "./common.h"
#include "../api.h"
#include "../../winamp/accessibilityConfigGroup.h"
#include <shlwapi.h>
#include <strsafe.h>
LPWSTR LoginBox_MallocString(size_t cchLen)
{
return (LPWSTR)calloc(cchLen, sizeof(WCHAR));
}
void LoginBox_FreeString(LPWSTR pszString)
{
if (NULL != pszString)
{
free(pszString);
}
}
void LoginBox_FreeStringSecure(LPWSTR pszString)
{
if (NULL != pszString)
{
size_t size = LoginBox_GetAllocSize(pszString);
if (0 != size)
SecureZeroMemory(pszString, size);
free(pszString);
}
}
LPWSTR LoginBox_ReAllocString(LPWSTR pszString, size_t cchLen)
{
return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen);
}
LPWSTR LoginBox_CopyString(LPCWSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenW(pszSource) + 1;
LPWSTR copy = LoginBox_MallocString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource);
}
return copy;
}
LPSTR LoginBox_MallocAnsiString(size_t cchLen)
{
return (LPSTR)calloc(cchLen, sizeof(CHAR));
}
LPSTR LoginBox_CopyAnsiString(LPCSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenA(pszSource) + 1;
LPSTR copy = LoginBox_MallocAnsiString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource);
}
return copy;
}
void LoginBox_FreeAnsiString(LPSTR pszString)
{
LoginBox_FreeString((LPWSTR)pszString);
}
void LoginBox_FreeAnsiStringSecure(LPSTR pszString)
{
LoginBox_FreeStringSecure((LPWSTR)pszString);
}
size_t LoginBox_GetAllocSize(void *memory)
{
return (NULL != memory) ? _msize(memory) : 0;
}
size_t LoginBox_GetStringMax(LPWSTR pszString)
{
return LoginBox_GetAllocSize(pszString)/sizeof(WCHAR);
}
size_t LoginBox_GetAnsiStringMax(LPSTR pszString)
{
return LoginBox_GetAllocSize(pszString)/sizeof(CHAR);
}
HRESULT LoginBox_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar, LPSTR *ppResult)
{
if (NULL == ppResult)
return E_POINTER;
INT resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cchWideChar > 0)
resultMax++;
*ppResult = LoginBox_MallocAnsiString(resultMax);
if (NULL == *ppResult) return E_OUTOFMEMORY;
resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, *ppResult, resultMax, lpDefaultChar, lpUsedDefaultChar);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
LoginBox_FreeAnsiString(*ppResult);
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cchWideChar > 0)
(*ppResult)[resultMax] = '\0';
return S_OK;
}
HRESULT LoginBox_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte, LPWSTR *ppResult)
{
if (NULL == ppResult)
return E_POINTER;
INT resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cbMultiByte > 0)
resultMax++;
*ppResult = LoginBox_MallocString(resultMax);
if (NULL == *ppResult) return E_OUTOFMEMORY;
resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, *ppResult, resultMax);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
LoginBox_FreeString(*ppResult);
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cbMultiByte > 0)
(*ppResult)[resultMax] = L'\0';
return S_OK;
}
HRESULT LoginBox_GetConfigPath(LPWSTR pszConfig, BOOL fEnsureExist)
{
if (NULL == pszConfig)
return E_INVALIDARG;
LPCWSTR pszWinamp;
pszWinamp = (NULL != WASABI_API_APP) ? WASABI_API_APP->path_getUserSettingsPath(): NULL;
if (NULL == pszWinamp)
return E_FAIL;
if (NULL == PathCombine(pszConfig, pszWinamp, L"Plugins\\loginBox"))
return E_FAIL;
if (FALSE != fEnsureExist)
{
HRESULT hr;
hr = LoginBox_EnsurePathExist(pszConfig);
if (FAILED(hr)) return hr;
}
return S_OK;
}
HRESULT LoginBox_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 LoginBox_GetWindowText(HWND hwnd, LPWSTR *ppszText, UINT *pcchText)
{
if (NULL == ppszText) return E_POINTER;
if (NULL == hwnd) return E_INVALIDARG;
UINT cchText = (UINT)SNDMSG(hwnd, WM_GETTEXTLENGTH, 0, 0L);
cchText++;
*ppszText = LoginBox_MallocString(cchText);
if (NULL == *ppszText)
{
if (NULL != pcchText) *pcchText = 0;
return E_OUTOFMEMORY;
}
cchText = (UINT)SNDMSG(hwnd, WM_GETTEXT, (WPARAM)cchText, (LPARAM)*ppszText);
if (NULL != pcchText)
*pcchText = cchText;
return S_OK;
}
BOOL LoginBox_PrintWindow(HWND hwnd, HDC hdc, UINT flags)
{
typedef BOOL (WINAPI *PRINTWINDOW)(HWND /*hwnd*/, HDC /*hdc*/, UINT /*nFlags*/);
static PRINTWINDOW printWindow = NULL;
static HMODULE moduleUser32 = NULL;
if (NULL == moduleUser32)
{
moduleUser32 = GetModuleHandle(L"USER32");
if (NULL == moduleUser32) return FALSE;
printWindow = (PRINTWINDOW)GetProcAddress(moduleUser32, "PrintWindow");
}
return (NULL != printWindow && FALSE != printWindow(hwnd, hdc, flags));
}
BOOL LoginBox_MessageBeep(UINT beepType)
{
BOOL result = FALSE;
ifc_configitem *beepEnabled = AGAVE_API_CONFIG->GetItem(accessibilityConfigGroupGUID, L"modalbeep");
if (NULL != beepEnabled)
{
if (false != beepEnabled->GetBool())
{
result = MessageBeep(beepType);
}
beepEnabled->Release();
}
return result;
}
HRESULT LoginBox_IsStringEqualEx(LCID locale, BOOL ignoreCase, LPCWSTR str1, LPCWSTR str2)
{
if ((NULL == str1) != (NULL == str2))
return S_FALSE;
if (NULL != str1 && CSTR_EQUAL != CompareString(locale, (FALSE != ignoreCase) ? NORM_IGNORECASE : 0, str1, -1, str2, -1))
return S_FALSE;
return S_OK;
}
UINT LoginBox_GetCurrentTime()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
if(FALSE == SystemTimeToFileTime(&st, &ft))
return 0;
ULARGE_INTEGER t1;
t1.LowPart = ft.dwLowDateTime;
t1.HighPart = ft.dwHighDateTime;
return (UINT)((t1.QuadPart - 116444736000000000) / 10000000);
}
HRESULT LoginBox_GetCurrentLang(LPSTR *ppLang)
{
if (NULL == ppLang)
return E_POINTER;
if (NULL == WASABI_API_LNG)
return E_UNEXPECTED;
LPCWSTR lang = WASABI_API_LNG->GetLanguageIdentifier(LANG_LANG_CODE);
if (NULL != lang && L'\0' != *lang)
return LoginBox_WideCharToMultiByte(CP_UTF8, 0, lang, -1, NULL, NULL, ppLang);
*ppLang = NULL;
return S_OK;
}
HDWP LoginBox_LayoutButtonBar(HDWP hdwp, HWND hwnd, const INT *buttonList, UINT buttonCount, const RECT *prcClient, LONG buttonHeight, LONG buttonSpace, BOOL fRedraw, RECT *prcResult)
{
if (NULL == hdwp && NULL == prcClient)
return NULL;
RECT rect;
CopyRect(&rect, prcClient);
LONG top = rect.bottom - buttonHeight;
if (top < rect.top) top = rect.top;
LONG height = rect.bottom - top;
LONG width;
LONG right = rect.right;
if (NULL == buttonList || 0 == buttonCount)
{
if (NULL != prcResult)
SetRect(prcResult, right, top, rect.right, top + height);
return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
}
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
WCHAR szText[256] = {0};
INT cchText;
HFONT font(NULL), fontOrig;
SIZE textSize;
RECT buttonRect;
while(buttonCount--)
{
HWND hControl = GetDlgItem(hwnd, buttonList[buttonCount]);
if (NULL == hControl || 0 == (WS_VISIBLE & GetWindowStyle(hControl)) ||
FALSE == GetWindowRect(hControl, &buttonRect))
{
continue;
}
if (right != rect.right)
right -= buttonSpace;
width = buttonRect.right - buttonRect.left;
cchText = (INT)SendMessage(hControl, WM_GETTEXT, (WPARAM)ARRAYSIZE(szText), (LPARAM)szText);
if (cchText > 0)
{
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL != hdc)
{
if (NULL == font)
font = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
fontOrig = (HFONT)SelectObject(hdc, font);
if (FALSE != GetTextExtentPoint32W(hdc, szText, cchText, &textSize))
{
width = textSize.cx + 4*LoginBox_GetAveCharWidth(hdc);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hControl, hdc);
}
}
if (width < 75)
width = 75;
if (NULL != hdwp)
{
hdwp = DeferWindowPos(hdwp, hControl, NULL, right - width, top, width, height, flags);
if (NULL == hdwp) return NULL;
}
right -= width;
}
if (NULL != prcResult)
SetRect(prcResult, right, top, rect.right, top + height);
return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
}
BYTE LoginBox_GetSysFontQuality()
{
BOOL smoothingEnabled;
if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
FALSE == smoothingEnabled)
{
return DEFAULT_QUALITY;
}
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (FALSE == GetVersionEx(&vi))
return DEFAULT_QUALITY;
if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
{
UINT smootingType;
if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
return DEFAULT_QUALITY;
if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
return CLEARTYPE_QUALITY;
}
return ANTIALIASED_QUALITY;
}
INT LoginBox_GetAveStrWidth(HDC hdc, INT cchLen)
{
const char szTest[] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l', 'm','n','o','p','q','r','s','t','u','v','w','x','y','z'
};
SIZE textSize;
if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
return 0;
INT result;
if (1 == cchLen)
{
result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
}
else
{
result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
if (0 != result)
{
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
result += tm.tmOverhang;
}
}
return result;
}
INT LoginBox_GetAveCharWidth(HDC hdc)
{
return LoginBox_GetAveStrWidth(hdc, 1);
}
BOOL LoginBox_GetWindowBaseUnits(HWND hwnd, INT *pBaseUnitX, INT *pBaseUnitY)
{
INT baseunitX(0), baseunitY(0);
BOOL result = FALSE;
if (NULL != hwnd)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
baseunitY = tm.tmHeight;
baseunitX = LoginBox_GetAveCharWidth(hdc);
result = TRUE;
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
}
if (NULL != pBaseUnitX) *pBaseUnitX = baseunitX;
if (NULL != pBaseUnitY) *pBaseUnitY = baseunitY;
return result;
}
INT LoginBox_GetWindowTextHeight(HWND hwnd, INT paddingDlgUnit)
{
if (NULL == hwnd) return 0;
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return 0;
INT height = 0;
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
height = tm.tmHeight;
if (0 != paddingDlgUnit)
height += MulDiv(2 * paddingDlgUnit, tm.tmHeight, 8);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
return height;
}
BOOL LoginBox_GetWindowTextSize(HWND hwnd, INT idealWidth, INT *pWidth, INT *pHeight)
{
INT width(0), height(0);
BOOL result = FALSE;
if (NULL != hwnd)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
LPWSTR pszText;
UINT cchText;
if (SUCCEEDED(LoginBox_GetWindowText(hwnd, &pszText, &cchText)))
{
if (0 == cchText)
{
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
height = tm.tmHeight;
width = 0;
result = TRUE;
}
}
else
{
RECT rect;
SetRect(&rect, 0, 0, idealWidth, 0);
if (0 != DrawText(hdc, pszText, cchText, &rect, DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK))
{
width = rect.right - rect.left;
height = rect.bottom - rect.top;
result = TRUE;
}
}
LoginBox_FreeString(pszText);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
}
if (NULL != pWidth) *pWidth = width;
if (NULL != pHeight) *pHeight = height;
return result;
}
BOOL LoginBox_OpenUrl(HWND hOwner, LPCWSTR pszUrl, BOOL forceExternal)
{
if (NULL == WASABI_API_WINAMP)
return FALSE;
HCURSOR hCursor = LoadCursor(NULL, IDC_APPSTARTING);
if (NULL != hCursor)
hCursor = SetCursor(hCursor);
BOOL result;
if (FALSE != forceExternal)
{
HINSTANCE hInst = ShellExecute(hOwner, L"open", pszUrl, NULL, NULL, SW_SHOWNORMAL);
result = ((INT_PTR)hInst > 32) ? TRUE: FALSE;
}
else
{
HRESULT hr = WASABI_API_WINAMP->OpenUrl(hOwner, pszUrl);
result = SUCCEEDED(hr);
}
if (NULL != hCursor)
SetCursor(hCursor);
return result;
}