1
0

common.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include "./common.h"
  2. #include "../api.h"
  3. #include "../../winamp/accessibilityConfigGroup.h"
  4. #include <shlwapi.h>
  5. #include <strsafe.h>
  6. LPWSTR LoginBox_MallocString(size_t cchLen)
  7. {
  8. return (LPWSTR)calloc(cchLen, sizeof(WCHAR));
  9. }
  10. void LoginBox_FreeString(LPWSTR pszString)
  11. {
  12. if (NULL != pszString)
  13. {
  14. free(pszString);
  15. }
  16. }
  17. void LoginBox_FreeStringSecure(LPWSTR pszString)
  18. {
  19. if (NULL != pszString)
  20. {
  21. size_t size = LoginBox_GetAllocSize(pszString);
  22. if (0 != size)
  23. SecureZeroMemory(pszString, size);
  24. free(pszString);
  25. }
  26. }
  27. LPWSTR LoginBox_ReAllocString(LPWSTR pszString, size_t cchLen)
  28. {
  29. return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen);
  30. }
  31. LPWSTR LoginBox_CopyString(LPCWSTR pszSource)
  32. {
  33. if (NULL == pszSource)
  34. return NULL;
  35. INT cchSource = lstrlenW(pszSource) + 1;
  36. LPWSTR copy = LoginBox_MallocString(cchSource);
  37. if (NULL != copy)
  38. {
  39. CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource);
  40. }
  41. return copy;
  42. }
  43. LPSTR LoginBox_MallocAnsiString(size_t cchLen)
  44. {
  45. return (LPSTR)calloc(cchLen, sizeof(CHAR));
  46. }
  47. LPSTR LoginBox_CopyAnsiString(LPCSTR pszSource)
  48. {
  49. if (NULL == pszSource)
  50. return NULL;
  51. INT cchSource = lstrlenA(pszSource) + 1;
  52. LPSTR copy = LoginBox_MallocAnsiString(cchSource);
  53. if (NULL != copy)
  54. {
  55. CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource);
  56. }
  57. return copy;
  58. }
  59. void LoginBox_FreeAnsiString(LPSTR pszString)
  60. {
  61. LoginBox_FreeString((LPWSTR)pszString);
  62. }
  63. void LoginBox_FreeAnsiStringSecure(LPSTR pszString)
  64. {
  65. LoginBox_FreeStringSecure((LPWSTR)pszString);
  66. }
  67. size_t LoginBox_GetAllocSize(void *memory)
  68. {
  69. return (NULL != memory) ? _msize(memory) : 0;
  70. }
  71. size_t LoginBox_GetStringMax(LPWSTR pszString)
  72. {
  73. return LoginBox_GetAllocSize(pszString)/sizeof(WCHAR);
  74. }
  75. size_t LoginBox_GetAnsiStringMax(LPSTR pszString)
  76. {
  77. return LoginBox_GetAllocSize(pszString)/sizeof(CHAR);
  78. }
  79. HRESULT LoginBox_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar, LPSTR *ppResult)
  80. {
  81. if (NULL == ppResult)
  82. return E_POINTER;
  83. INT resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
  84. if (0 == resultMax)
  85. {
  86. DWORD errorCode = GetLastError();
  87. *ppResult = NULL;
  88. return HRESULT_FROM_WIN32(errorCode);
  89. }
  90. if (cchWideChar > 0)
  91. resultMax++;
  92. *ppResult = LoginBox_MallocAnsiString(resultMax);
  93. if (NULL == *ppResult) return E_OUTOFMEMORY;
  94. resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, *ppResult, resultMax, lpDefaultChar, lpUsedDefaultChar);
  95. if (0 == resultMax)
  96. {
  97. DWORD errorCode = GetLastError();
  98. LoginBox_FreeAnsiString(*ppResult);
  99. *ppResult = NULL;
  100. return HRESULT_FROM_WIN32(errorCode);
  101. }
  102. if (cchWideChar > 0)
  103. (*ppResult)[resultMax] = '\0';
  104. return S_OK;
  105. }
  106. HRESULT LoginBox_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte, LPWSTR *ppResult)
  107. {
  108. if (NULL == ppResult)
  109. return E_POINTER;
  110. INT resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
  111. if (0 == resultMax)
  112. {
  113. DWORD errorCode = GetLastError();
  114. *ppResult = NULL;
  115. return HRESULT_FROM_WIN32(errorCode);
  116. }
  117. if (cbMultiByte > 0)
  118. resultMax++;
  119. *ppResult = LoginBox_MallocString(resultMax);
  120. if (NULL == *ppResult) return E_OUTOFMEMORY;
  121. resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, *ppResult, resultMax);
  122. if (0 == resultMax)
  123. {
  124. DWORD errorCode = GetLastError();
  125. LoginBox_FreeString(*ppResult);
  126. *ppResult = NULL;
  127. return HRESULT_FROM_WIN32(errorCode);
  128. }
  129. if (cbMultiByte > 0)
  130. (*ppResult)[resultMax] = L'\0';
  131. return S_OK;
  132. }
  133. HRESULT LoginBox_GetConfigPath(LPWSTR pszConfig, BOOL fEnsureExist)
  134. {
  135. if (NULL == pszConfig)
  136. return E_INVALIDARG;
  137. LPCWSTR pszWinamp;
  138. pszWinamp = (NULL != WASABI_API_APP) ? WASABI_API_APP->path_getUserSettingsPath(): NULL;
  139. if (NULL == pszWinamp)
  140. return E_FAIL;
  141. if (NULL == PathCombine(pszConfig, pszWinamp, L"Plugins\\loginBox"))
  142. return E_FAIL;
  143. if (FALSE != fEnsureExist)
  144. {
  145. HRESULT hr;
  146. hr = LoginBox_EnsurePathExist(pszConfig);
  147. if (FAILED(hr)) return hr;
  148. }
  149. return S_OK;
  150. }
  151. HRESULT LoginBox_EnsurePathExist(LPCWSTR pszDirectory)
  152. {
  153. DWORD ec = ERROR_SUCCESS;
  154. UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  155. if (0 == CreateDirectory(pszDirectory, NULL))
  156. {
  157. ec = GetLastError();
  158. if (ERROR_PATH_NOT_FOUND == ec)
  159. {
  160. LPCWSTR pszBlock = pszDirectory;
  161. WCHAR szBuffer[MAX_PATH] = {0};
  162. LPCTSTR pszCursor = PathFindNextComponent(pszBlock);
  163. ec = (pszCursor == pszBlock || S_OK != StringCchCopyN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock))) ?
  164. ERROR_INVALID_NAME : ERROR_SUCCESS;
  165. pszBlock = pszCursor;
  166. while (ERROR_SUCCESS == ec && NULL != (pszCursor = PathFindNextComponent(pszBlock)))
  167. {
  168. if (pszCursor == pszBlock || S_OK != StringCchCatN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock)))
  169. ec = ERROR_INVALID_NAME;
  170. if (ERROR_SUCCESS == ec && !CreateDirectory(szBuffer, NULL))
  171. {
  172. ec = GetLastError();
  173. if (ERROR_ALREADY_EXISTS == ec) ec = ERROR_SUCCESS;
  174. }
  175. pszBlock = pszCursor;
  176. }
  177. }
  178. if (ERROR_ALREADY_EXISTS == ec)
  179. ec = ERROR_SUCCESS;
  180. }
  181. SetErrorMode(errorMode);
  182. SetLastError(ec);
  183. return HRESULT_FROM_WIN32(ec);
  184. }
  185. HRESULT LoginBox_GetWindowText(HWND hwnd, LPWSTR *ppszText, UINT *pcchText)
  186. {
  187. if (NULL == ppszText) return E_POINTER;
  188. if (NULL == hwnd) return E_INVALIDARG;
  189. UINT cchText = (UINT)SNDMSG(hwnd, WM_GETTEXTLENGTH, 0, 0L);
  190. cchText++;
  191. *ppszText = LoginBox_MallocString(cchText);
  192. if (NULL == *ppszText)
  193. {
  194. if (NULL != pcchText) *pcchText = 0;
  195. return E_OUTOFMEMORY;
  196. }
  197. cchText = (UINT)SNDMSG(hwnd, WM_GETTEXT, (WPARAM)cchText, (LPARAM)*ppszText);
  198. if (NULL != pcchText)
  199. *pcchText = cchText;
  200. return S_OK;
  201. }
  202. BOOL LoginBox_PrintWindow(HWND hwnd, HDC hdc, UINT flags)
  203. {
  204. typedef BOOL (WINAPI *PRINTWINDOW)(HWND /*hwnd*/, HDC /*hdc*/, UINT /*nFlags*/);
  205. static PRINTWINDOW printWindow = NULL;
  206. static HMODULE moduleUser32 = NULL;
  207. if (NULL == moduleUser32)
  208. {
  209. moduleUser32 = GetModuleHandle(L"USER32");
  210. if (NULL == moduleUser32) return FALSE;
  211. printWindow = (PRINTWINDOW)GetProcAddress(moduleUser32, "PrintWindow");
  212. }
  213. return (NULL != printWindow && FALSE != printWindow(hwnd, hdc, flags));
  214. }
  215. BOOL LoginBox_MessageBeep(UINT beepType)
  216. {
  217. BOOL result = FALSE;
  218. ifc_configitem *beepEnabled = AGAVE_API_CONFIG->GetItem(accessibilityConfigGroupGUID, L"modalbeep");
  219. if (NULL != beepEnabled)
  220. {
  221. if (false != beepEnabled->GetBool())
  222. {
  223. result = MessageBeep(beepType);
  224. }
  225. beepEnabled->Release();
  226. }
  227. return result;
  228. }
  229. HRESULT LoginBox_IsStringEqualEx(LCID locale, BOOL ignoreCase, LPCWSTR str1, LPCWSTR str2)
  230. {
  231. if ((NULL == str1) != (NULL == str2))
  232. return S_FALSE;
  233. if (NULL != str1 && CSTR_EQUAL != CompareString(locale, (FALSE != ignoreCase) ? NORM_IGNORECASE : 0, str1, -1, str2, -1))
  234. return S_FALSE;
  235. return S_OK;
  236. }
  237. UINT LoginBox_GetCurrentTime()
  238. {
  239. SYSTEMTIME st;
  240. FILETIME ft;
  241. GetSystemTime(&st);
  242. if(FALSE == SystemTimeToFileTime(&st, &ft))
  243. return 0;
  244. ULARGE_INTEGER t1;
  245. t1.LowPart = ft.dwLowDateTime;
  246. t1.HighPart = ft.dwHighDateTime;
  247. return (UINT)((t1.QuadPart - 116444736000000000) / 10000000);
  248. }
  249. HRESULT LoginBox_GetCurrentLang(LPSTR *ppLang)
  250. {
  251. if (NULL == ppLang)
  252. return E_POINTER;
  253. if (NULL == WASABI_API_LNG)
  254. return E_UNEXPECTED;
  255. LPCWSTR lang = WASABI_API_LNG->GetLanguageIdentifier(LANG_LANG_CODE);
  256. if (NULL != lang && L'\0' != *lang)
  257. return LoginBox_WideCharToMultiByte(CP_UTF8, 0, lang, -1, NULL, NULL, ppLang);
  258. *ppLang = NULL;
  259. return S_OK;
  260. }
  261. HDWP LoginBox_LayoutButtonBar(HDWP hdwp, HWND hwnd, const INT *buttonList, UINT buttonCount, const RECT *prcClient, LONG buttonHeight, LONG buttonSpace, BOOL fRedraw, RECT *prcResult)
  262. {
  263. if (NULL == hdwp && NULL == prcClient)
  264. return NULL;
  265. RECT rect;
  266. CopyRect(&rect, prcClient);
  267. LONG top = rect.bottom - buttonHeight;
  268. if (top < rect.top) top = rect.top;
  269. LONG height = rect.bottom - top;
  270. LONG width;
  271. LONG right = rect.right;
  272. if (NULL == buttonList || 0 == buttonCount)
  273. {
  274. if (NULL != prcResult)
  275. SetRect(prcResult, right, top, rect.right, top + height);
  276. return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
  277. }
  278. UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
  279. if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
  280. WCHAR szText[256] = {0};
  281. INT cchText;
  282. HFONT font(NULL), fontOrig;
  283. SIZE textSize;
  284. RECT buttonRect;
  285. while(buttonCount--)
  286. {
  287. HWND hControl = GetDlgItem(hwnd, buttonList[buttonCount]);
  288. if (NULL == hControl || 0 == (WS_VISIBLE & GetWindowStyle(hControl)) ||
  289. FALSE == GetWindowRect(hControl, &buttonRect))
  290. {
  291. continue;
  292. }
  293. if (right != rect.right)
  294. right -= buttonSpace;
  295. width = buttonRect.right - buttonRect.left;
  296. cchText = (INT)SendMessage(hControl, WM_GETTEXT, (WPARAM)ARRAYSIZE(szText), (LPARAM)szText);
  297. if (cchText > 0)
  298. {
  299. HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
  300. if (NULL != hdc)
  301. {
  302. if (NULL == font)
  303. font = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
  304. fontOrig = (HFONT)SelectObject(hdc, font);
  305. if (FALSE != GetTextExtentPoint32W(hdc, szText, cchText, &textSize))
  306. {
  307. width = textSize.cx + 4*LoginBox_GetAveCharWidth(hdc);
  308. }
  309. SelectObject(hdc, fontOrig);
  310. ReleaseDC(hControl, hdc);
  311. }
  312. }
  313. if (width < 75)
  314. width = 75;
  315. if (NULL != hdwp)
  316. {
  317. hdwp = DeferWindowPos(hdwp, hControl, NULL, right - width, top, width, height, flags);
  318. if (NULL == hdwp) return NULL;
  319. }
  320. right -= width;
  321. }
  322. if (NULL != prcResult)
  323. SetRect(prcResult, right, top, rect.right, top + height);
  324. return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
  325. }
  326. BYTE LoginBox_GetSysFontQuality()
  327. {
  328. BOOL smoothingEnabled;
  329. if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
  330. FALSE == smoothingEnabled)
  331. {
  332. return DEFAULT_QUALITY;
  333. }
  334. OSVERSIONINFO vi;
  335. vi.dwOSVersionInfoSize = sizeof(vi);
  336. if (FALSE == GetVersionEx(&vi))
  337. return DEFAULT_QUALITY;
  338. if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
  339. {
  340. UINT smootingType;
  341. if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
  342. return DEFAULT_QUALITY;
  343. if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
  344. return CLEARTYPE_QUALITY;
  345. }
  346. return ANTIALIASED_QUALITY;
  347. }
  348. INT LoginBox_GetAveStrWidth(HDC hdc, INT cchLen)
  349. {
  350. const char szTest[] =
  351. {
  352. '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',
  353. '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'
  354. };
  355. SIZE textSize;
  356. if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
  357. return 0;
  358. INT result;
  359. if (1 == cchLen)
  360. {
  361. result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
  362. }
  363. else
  364. {
  365. result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
  366. if (0 != result)
  367. {
  368. TEXTMETRIC tm;
  369. if (FALSE != GetTextMetrics(hdc, &tm))
  370. result += tm.tmOverhang;
  371. }
  372. }
  373. return result;
  374. }
  375. INT LoginBox_GetAveCharWidth(HDC hdc)
  376. {
  377. return LoginBox_GetAveStrWidth(hdc, 1);
  378. }
  379. BOOL LoginBox_GetWindowBaseUnits(HWND hwnd, INT *pBaseUnitX, INT *pBaseUnitY)
  380. {
  381. INT baseunitX(0), baseunitY(0);
  382. BOOL result = FALSE;
  383. if (NULL != hwnd)
  384. {
  385. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  386. if (NULL != hdc)
  387. {
  388. HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
  389. HFONT fontOrig = (HFONT)SelectObject(hdc, font);
  390. TEXTMETRIC tm;
  391. if (FALSE != GetTextMetrics(hdc, &tm))
  392. {
  393. baseunitY = tm.tmHeight;
  394. baseunitX = LoginBox_GetAveCharWidth(hdc);
  395. result = TRUE;
  396. }
  397. SelectObject(hdc, fontOrig);
  398. ReleaseDC(hwnd, hdc);
  399. }
  400. }
  401. if (NULL != pBaseUnitX) *pBaseUnitX = baseunitX;
  402. if (NULL != pBaseUnitY) *pBaseUnitY = baseunitY;
  403. return result;
  404. }
  405. INT LoginBox_GetWindowTextHeight(HWND hwnd, INT paddingDlgUnit)
  406. {
  407. if (NULL == hwnd) return 0;
  408. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  409. if (NULL == hdc) return 0;
  410. INT height = 0;
  411. HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
  412. HFONT fontOrig = (HFONT)SelectObject(hdc, font);
  413. TEXTMETRIC tm;
  414. if (FALSE != GetTextMetrics(hdc, &tm))
  415. {
  416. height = tm.tmHeight;
  417. if (0 != paddingDlgUnit)
  418. height += MulDiv(2 * paddingDlgUnit, tm.tmHeight, 8);
  419. }
  420. SelectObject(hdc, fontOrig);
  421. ReleaseDC(hwnd, hdc);
  422. return height;
  423. }
  424. BOOL LoginBox_GetWindowTextSize(HWND hwnd, INT idealWidth, INT *pWidth, INT *pHeight)
  425. {
  426. INT width(0), height(0);
  427. BOOL result = FALSE;
  428. if (NULL != hwnd)
  429. {
  430. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  431. if (NULL != hdc)
  432. {
  433. HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
  434. HFONT fontOrig = (HFONT)SelectObject(hdc, font);
  435. LPWSTR pszText;
  436. UINT cchText;
  437. if (SUCCEEDED(LoginBox_GetWindowText(hwnd, &pszText, &cchText)))
  438. {
  439. if (0 == cchText)
  440. {
  441. TEXTMETRIC tm;
  442. if (FALSE != GetTextMetrics(hdc, &tm))
  443. {
  444. height = tm.tmHeight;
  445. width = 0;
  446. result = TRUE;
  447. }
  448. }
  449. else
  450. {
  451. RECT rect;
  452. SetRect(&rect, 0, 0, idealWidth, 0);
  453. if (0 != DrawText(hdc, pszText, cchText, &rect, DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK))
  454. {
  455. width = rect.right - rect.left;
  456. height = rect.bottom - rect.top;
  457. result = TRUE;
  458. }
  459. }
  460. LoginBox_FreeString(pszText);
  461. }
  462. SelectObject(hdc, fontOrig);
  463. ReleaseDC(hwnd, hdc);
  464. }
  465. }
  466. if (NULL != pWidth) *pWidth = width;
  467. if (NULL != pHeight) *pHeight = height;
  468. return result;
  469. }
  470. BOOL LoginBox_OpenUrl(HWND hOwner, LPCWSTR pszUrl, BOOL forceExternal)
  471. {
  472. if (NULL == WASABI_API_WINAMP)
  473. return FALSE;
  474. HCURSOR hCursor = LoadCursor(NULL, IDC_APPSTARTING);
  475. if (NULL != hCursor)
  476. hCursor = SetCursor(hCursor);
  477. BOOL result;
  478. if (FALSE != forceExternal)
  479. {
  480. HINSTANCE hInst = ShellExecute(hOwner, L"open", pszUrl, NULL, NULL, SW_SHOWNORMAL);
  481. result = ((INT_PTR)hInst > 32) ? TRUE: FALSE;
  482. }
  483. else
  484. {
  485. HRESULT hr = WASABI_API_WINAMP->OpenUrl(hOwner, pszUrl);
  486. result = SUCCEEDED(hr);
  487. }
  488. if (NULL != hCursor)
  489. SetCursor(hCursor);
  490. return result;
  491. }