#include "./common.h" #include "../api.h" #include "../../winamp/accessibilityConfigGroup.h" #include #include 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; }