1
0

util.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include <windows.h>
  10. #include "strutil.h"
  11. #include "../nu/ns_wc.h"
  12. #include "plush/plush.h"
  13. #include "../nu/AutoChar.h"
  14. #include "../nu/AutoWide.h"
  15. #include "WinampAttributes.h"
  16. #undef GetSystemMetrics
  17. int IsUrl(const char *url)
  18. {
  19. return !!strstr(url, "://");
  20. }
  21. void link_startsubclass(HWND hwndDlg, UINT id){
  22. HWND ctrl = GetDlgItem(hwndDlg, id);
  23. if(!GetPropW(ctrl, L"link_proc"))
  24. {
  25. SetPropW(ctrl, L"link_proc",
  26. (HANDLE)SetWindowLongPtrW(ctrl, GWLP_WNDPROC, (LONG_PTR)link_handlecursor));
  27. }
  28. }
  29. static HCURSOR link_hand_cursor;
  30. LRESULT link_handlecursor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  31. {
  32. LRESULT ret = CallWindowProcW((WNDPROC)GetPropW(hwndDlg, L"link_proc"), hwndDlg, uMsg, wParam, lParam);
  33. // override the normal cursor behaviour so we have a hand to show it is a link
  34. if(uMsg == WM_SETCURSOR)
  35. {
  36. if((HWND)wParam == hwndDlg)
  37. {
  38. if(!link_hand_cursor)
  39. {
  40. link_hand_cursor = LoadCursor(NULL, IDC_HAND);
  41. }
  42. SetCursor(link_hand_cursor);
  43. return TRUE;
  44. }
  45. }
  46. return ret;
  47. }
  48. void link_handledraw(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  49. {
  50. if (uMsg == WM_DRAWITEM)
  51. {
  52. DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
  53. if (di->CtlType == ODT_BUTTON)
  54. {
  55. wchar_t wt[123] = {0};
  56. int y;
  57. RECT r;
  58. HPEN hPen, hOldPen;
  59. GetDlgItemTextW(hwndDlg, wParam, wt, sizeof(wt)/sizeof(wt[0]));
  60. // draw text
  61. SetTextColor(di->hDC, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  62. r = di->rcItem;
  63. // is used by the file types page to have a slimmer button so it doesn't override other
  64. // characters which are otherwise drawn over by the size of the button needed for a link
  65. if(GetPropW(di->hwndItem, L"slim"))
  66. {
  67. r.top -= 2;
  68. }
  69. r.left += 2;
  70. DrawTextW(di->hDC, wt, -1, &r, DT_VCENTER | DT_SINGLELINE);
  71. memset(&r, 0, sizeof(r));
  72. DrawTextW(di->hDC, wt, -1, &r, DT_SINGLELINE | DT_CALCRECT);
  73. // draw underline
  74. y = di->rcItem.bottom - ((di->rcItem.bottom - di->rcItem.top) - (r.bottom - r.top)) / 2 - 1;
  75. hPen = CreatePen(PS_SOLID, 0, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
  76. hOldPen = (HPEN) SelectObject(di->hDC, hPen);
  77. MoveToEx(di->hDC, di->rcItem.left + 2, y, NULL);
  78. LineTo(di->hDC, di->rcItem.right + 2 - ((di->rcItem.right - di->rcItem.left) - (r.right - r.left)), y);
  79. SelectObject(di->hDC, hOldPen);
  80. DeleteObject(hPen);
  81. }
  82. }
  83. }
  84. ///////// if you update this, be sure to update the copy of it in $/winampa/winampicon.c
  85. // thx.
  86. int geticonid(int x)
  87. {
  88. switch (x) {
  89. case 1: return IDI_FILEICON;
  90. case 2: return IDI_FILEICON2;
  91. case 3: return IDI_FILEICON3;
  92. case 4: return IDI_FILEICON10;
  93. case 5: return IDI_FILEICON5;
  94. case 6: return IDI_FILEICON6;
  95. case 7: return IDI_FILEICON7;
  96. case 8: return IDI_FILEICON8;
  97. case 9: return IDI_FILEICON9;
  98. case 10: return IDI_FILEICON4;
  99. case 11: return IDI_FILEICON11;
  100. case 12: return ICON_TB1;
  101. case 13: return -666;
  102. default: return ICON_XP;
  103. }
  104. }
  105. /*
  106. void plSplineGetPoint(pl_Spline *s, float frame, float *out)
  107. {
  108. int i, i_1, i0, i1, i2;
  109. float time1, time2, time3;
  110. float t1, t2, t3, t4, u1, u2, u3, u4, v1, v2, v3;
  111. float a, b, c, d;
  112. float *keys = s->keys;
  113. a = (1 - s->tens) * (1 + s->cont) * (1 + s->bias);
  114. b = (1 - s->tens) * (1 - s->cont) * (1 - s->bias);
  115. c = (1 - s->tens) * (1 - s->cont) * (1 + s->bias);
  116. d = (1 - s->tens) * (1 + s->cont) * (1 - s->bias);
  117. v1 = t1 = -a / 2.0f; u1 = a;
  118. u2 = ( -6 - 2 * a + 2 * b + c) / 2.0f; v2 = (a - b) / 2.0f; t2 = (4 + a - b - c) / 2.0f;
  119. t3 = ( -4 + b + c - d) / 2.0f;
  120. u3 = (6 - 2 * b - c + d) / 2.0f;
  121. v3 = b / 2.0f;
  122. t4 = d / 2.0f; u4 = -t4;
  123. i0 = (int) frame;
  124. i_1 = i0 - 1;
  125. while (i_1 < 0) i_1 += s->numKeys;
  126. i1 = i0 + 1;
  127. while (i1 >= s->numKeys) i1 -= s->numKeys;
  128. i2 = i0 + 2;
  129. while (i2 >= s->numKeys) i2 -= s->numKeys;
  130. time1 = frame - (float) ((int) frame);
  131. time2 = time1 * time1;
  132. time3 = time2 * time1;
  133. i0 *= s->keyWidth;
  134. i1 *= s->keyWidth;
  135. i2 *= s->keyWidth;
  136. i_1 *= s->keyWidth;
  137. for (i = 0; i < s->keyWidth; i ++)
  138. {
  139. a = t1 * keys[i + i_1] + t2 * keys[i + i0] + t3 * keys[i + i1] + t4 * keys[i + i2];
  140. b = u1 * keys[i + i_1] + u2 * keys[i + i0] + u3 * keys[i + i1] + u4 * keys[i + i2];
  141. c = v1 * keys[i + i_1] + v2 * keys[i + i0] + v3 * keys[i + i1];
  142. *out++ = a * time3 + b * time2 + c * time1 + keys[i + i0];
  143. }
  144. }
  145. */
  146. //int transAccel(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  147. //{
  148. // HACCEL h;
  149. // MSG msg;
  150. // if (hwnd == hMainWindow) h = hAccel[0];
  151. // else if (hwnd == hEQWindow) h = hAccel[1];
  152. // else if (hwnd == hPLWindow) h = hAccel[2];
  153. // // else if (hwnd==hMBWindow) h=hAccel[3];
  154. // else if (hwnd == hVideoWindow || GetParent(hwnd) == hVideoWindow)
  155. // {
  156. // h = hAccel[0];
  157. // }
  158. // else
  159. // {
  160. // return 0;
  161. // }
  162. // msg.hwnd = hwnd;
  163. // msg.lParam = lParam;
  164. // msg.message = uMsg;
  165. // msg.wParam = wParam;
  166. // return TranslateAccelerator(hwnd, h, &msg);
  167. //
  168. //}
  169. #include <pshpack4.h>
  170. typedef struct
  171. {
  172. DWORD dwSize;
  173. HANDLE hrasconn;
  174. char szEntryName[256 + 1];
  175. char szDeviceType[ 16 + 1 ];
  176. char szDeviceName[ 128 + 1 ];
  177. }
  178. RASCONN ;
  179. #include <poppack.h>
  180. typedef DWORD (WINAPI *RASENUMCONNECTIONS)(RASCONN *lprasconn,
  181. LPDWORD lpcb,
  182. LPDWORD lpcConnections);
  183. static int isRASActive()
  184. {
  185. int r = 0;
  186. HINSTANCE h = LoadLibraryA("rasapi32.dll");
  187. RASENUMCONNECTIONS RasEnumConnections;
  188. RASCONN v = {sizeof(RASCONN), };
  189. DWORD i = sizeof(v), o = 0;
  190. if (!h) return 0;
  191. RasEnumConnections = (RASENUMCONNECTIONS)GetProcAddress(h, "RasEnumConnectionsA");
  192. if (RasEnumConnections && !RasEnumConnections(&v, &i, &o) && o) r = 1;
  193. FreeModule(h);
  194. return r;
  195. }
  196. int isInetAvailable(void)
  197. {
  198. if (config_inet_mode == 3)
  199. {
  200. if (isRASActive()) config_inet_mode = 1;
  201. else config_inet_mode = 0;
  202. return (1 == config_inet_mode);
  203. }
  204. if (config_inet_mode == 0) return 1;
  205. if (config_inet_mode == 2) return 0;
  206. return isRASActive();
  207. }
  208. unsigned int getDay(void)
  209. {
  210. unsigned int day = 0;
  211. SYSTEMTIME tm, st = {0, };
  212. FILETIME ft1, ft2;
  213. ULARGE_INTEGER l1, l2;
  214. GetSystemTime(&tm);
  215. st.wYear = 1978;
  216. st.wMonth = 10;
  217. st.wDay = 14;
  218. SystemTimeToFileTime(&tm, &ft1);
  219. SystemTimeToFileTime(&st, &ft2);
  220. memcpy(&l1, &ft1, sizeof(l1));
  221. memcpy(&l2, &ft2, sizeof(l2));
  222. day = (int) ((l1.QuadPart - l2.QuadPart) / (10 * 1000 * 1000) / (60 * 60 * 24));
  223. return day;
  224. }
  225. void recent_add(const wchar_t *loc)
  226. {
  227. wchar_t ls[MAX_PATH] = {0};
  228. _r_sW("RecentURL1", ls, MAX_PATH);
  229. _w_sW("RecentURL1", loc);
  230. if (wcscmp(ls, loc))
  231. {
  232. int x = 2;
  233. while(1)
  234. {
  235. char s[123] = {0};
  236. wchar_t temp[MAX_PATH] = {0};
  237. StringCchPrintfA(s, 123, "RecentURL%d", x);
  238. _r_sW(s, temp, MAX_PATH);
  239. if (ls[0]) _w_sW(s, ls);
  240. if (!_wcsicmp(temp, loc) || !temp[0])
  241. break;
  242. lstrcpynW(ls, temp, MAX_PATH);
  243. x++;
  244. }
  245. }
  246. }
  247. #include <assert.h>
  248. void getViewport(RECT *r, HWND wnd, int full, RECT *sr)
  249. {
  250. POINT *p = NULL;
  251. if (p || sr || wnd)
  252. {
  253. HMONITOR hm = NULL;
  254. if (sr)
  255. hm = MonitorFromRect(sr, MONITOR_DEFAULTTONEAREST);
  256. else if (wnd)
  257. hm = MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST);
  258. else if (p)
  259. hm = MonitorFromPoint(*p, MONITOR_DEFAULTTONEAREST);
  260. if (hm)
  261. {
  262. MONITORINFOEXW mi;
  263. memset(&mi, 0, sizeof(mi));
  264. mi.cbSize = sizeof(mi);
  265. if (GetMonitorInfoW(hm, &mi))
  266. {
  267. if (!full)
  268. *r = mi.rcWork;
  269. else
  270. *r = mi.rcMonitor;
  271. return ;
  272. }
  273. }
  274. }
  275. if (full)
  276. { // this might be borked =)
  277. r->top = r->left = 0;
  278. r->right = GetSystemMetrics(SM_CXSCREEN);
  279. r->bottom = GetSystemMetrics(SM_CYSCREEN);
  280. }
  281. else
  282. {
  283. SystemParametersInfoW(SPI_GETWORKAREA, 0, r, 0);
  284. }
  285. }
  286. BOOL windowOffScreen(HWND hwnd, POINT pt)
  287. {
  288. RECT r = {0}, wnd = {0}, sr = {0};
  289. GetWindowRect(hwnd, &wnd);
  290. sr.left = pt.x;
  291. sr.top = pt.y;
  292. sr.right = sr.left + (wnd.right - wnd.left);
  293. sr.bottom = sr.top + (wnd.bottom - wnd.top);
  294. getViewport(&r, hwnd, 0, &sr);
  295. return !PtInRect(&r, pt);
  296. }
  297. void readwrite_client_uid(int isWrite, wchar_t uid_str[64])
  298. {
  299. HKEY hkey;
  300. wchar_t path[MAX_PATH] = {0};
  301. GetModuleFileNameW(0, path, MAX_PATH);
  302. if (isWrite)
  303. {
  304. IFileTypeRegistrar *registrar=0;
  305. if (GetRegistrar(&registrar, true) == 0 && registrar)
  306. {
  307. registrar->WriteClientUIDKey(path, uid_str);
  308. registrar->Release();
  309. }
  310. return;
  311. }
  312. if (!isWrite) *uid_str = 0;
  313. if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Nullsoft\\Winamp", 0, 0, 0, KEY_READ, NULL, &hkey, NULL) == ERROR_SUCCESS)
  314. {
  315. DWORD s = 512, t = REG_SZ;
  316. if (RegQueryValueExW(hkey, path, 0, &t, (LPBYTE)uid_str, &s) != ERROR_SUCCESS || t != REG_SZ) uid_str[0] = 0;
  317. RegCloseKey(hkey);
  318. }
  319. }
  320. BOOL read_compatmode()
  321. {
  322. HKEY hkey = NULL;
  323. wchar_t path[MAX_PATH] = {0};
  324. GetModuleFileNameW(0, path, MAX_PATH);
  325. if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, 0, 0, KEY_READ, NULL, &hkey, NULL) == ERROR_SUCCESS)
  326. {
  327. DWORD s = 512, t = REG_SZ;
  328. wchar_t buf[128] = {0};
  329. if (RegQueryValueExW(hkey, path, 0, &t, (LPBYTE)buf, &s) != ERROR_SUCCESS || t != REG_SZ) buf[0] = 0;
  330. RegCloseKey(hkey);
  331. wchar_t *p = buf, *fields[] = {L"256COLOR", L"640X480", L"DISABLETHEMES", L"$",
  332. L"DISABLEDWM", L"DISABLEUSERCALLBACKEXCEPTION",
  333. L"HIGHDPIAWARE", L"RUNASADMIN", L"IGNOREFREELIBRARY",
  334. L"ELEVATECREATEPROCESS", L"#", L"~", L"PLACEHOLDERFILES"};
  335. int fields_len[] = {8, 7, 13, 1, 10, 28, 12, 10, 17, 20, 1, 1, 16};
  336. while (p && *p)
  337. {
  338. wchar_t *pp = p;
  339. while (pp && *pp && *pp != L' ')
  340. {
  341. pp = CharNextW(pp);
  342. }
  343. wchar_t pp_old = (pp ? *pp : 0);
  344. if (pp && *pp) *pp = 0;
  345. bool found = false;
  346. for (int i = 0; i < sizeof(fields)/sizeof(fields[0]); i++)
  347. {
  348. if (!wcsncmp(fields[i], p, fields_len[i]))
  349. found = true;
  350. }
  351. if (!found)
  352. return TRUE;
  353. if (pp) *pp = pp_old;
  354. if (!pp_old) break;
  355. p = CharNextW(pp);
  356. }
  357. }
  358. return FALSE;
  359. }
  360. BOOL IsVista(void)
  361. {
  362. static INT fVista = -1;
  363. if (-1 == fVista)
  364. {
  365. OSVERSIONINFO osver = {0};
  366. osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  367. fVista = (::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT && (osver.dwMajorVersion >= 6)) ? 1 : 0;
  368. }
  369. return (1 == fVista);
  370. }
  371. BOOL IsVistaOrLower(void)
  372. {
  373. static INT fVistaOrLower = -1;
  374. if (-1 == fVistaOrLower)
  375. {
  376. OSVERSIONINFO osver = {0};
  377. osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  378. fVistaOrLower = (::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  379. (osver.dwMajorVersion <= 5 || (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0))) ? 1 : 0;
  380. }
  381. return (1 == fVistaOrLower);
  382. }
  383. BOOL IsWin8(void)
  384. {
  385. static INT fWin8 = -1;
  386. if (-1 == fWin8)
  387. {
  388. OSVERSIONINFO osver = {0};
  389. osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  390. fWin8 = ( ::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT && (osver.dwMajorVersion > 6 || (osver.dwMajorVersion == 6 && osver.dwMinorVersion >= 2))) ? 1 : 0;
  391. }
  392. return (1 == fWin8);
  393. }
  394. //XP Theme crap
  395. typedef HRESULT (WINAPI * ENABLETHEMEDIALOGTEXTURE)(HWND, DWORD);
  396. int IsWinXPTheme(void)
  397. {
  398. static int previousRet = -1;
  399. if (previousRet == -1)
  400. {
  401. BOOL bEnabled(FALSE);
  402. OSVERSIONINFO vi;
  403. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  404. if (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0)))
  405. {
  406. HINSTANCE dll = LoadLibraryW(TEXT("uxtheme.dll"));
  407. if (dll)
  408. {
  409. BOOL (WINAPI *waIsAppThemed)(void);
  410. BOOL (WINAPI *waIsThemeActive)(void);
  411. waIsAppThemed = (BOOL (WINAPI *)())GetProcAddress(dll, "IsAppThemed");
  412. waIsThemeActive = (BOOL (WINAPI *)())GetProcAddress(dll, "IsThemeActive");
  413. if (waIsAppThemed && waIsThemeActive && waIsAppThemed() && waIsThemeActive())
  414. {
  415. HMODULE hComCtl = LoadLibraryW(TEXT("comctl32.dll"));
  416. if (hComCtl)
  417. {
  418. HRESULT (CALLBACK *waDllGetVersion)(DLLVERSIONINFO*) = (HRESULT (CALLBACK *)(DLLVERSIONINFO*))GetProcAddress(hComCtl, "DllGetVersion");
  419. if (waDllGetVersion)
  420. {
  421. DLLVERSIONINFO dllVer;
  422. dllVer.cbSize = sizeof(DLLVERSIONINFO);
  423. if (S_OK == waDllGetVersion(&dllVer) && dllVer.dwMajorVersion >= 6) bEnabled = TRUE;
  424. }
  425. FreeLibrary(hComCtl);
  426. }
  427. }
  428. FreeLibrary(dll);
  429. }
  430. }
  431. previousRet = bEnabled;
  432. }
  433. return previousRet;
  434. }
  435. void DoWinXPStyle(HWND tab)
  436. {
  437. WAEnableThemeDialogTexture(tab, ETDT_ENABLETAB);
  438. }
  439. HRESULT WAEnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
  440. {
  441. static int uxThemeTried = 0;
  442. static ENABLETHEMEDIALOGTEXTURE pfnETDT = NULL;
  443. if(!uxThemeTried)
  444. {
  445. HINSTANCE ux_hDll;
  446. if ((ux_hDll = LoadLibraryA("uxtheme.dll")) != NULL)
  447. pfnETDT = (ENABLETHEMEDIALOGTEXTURE)GetProcAddress(ux_hDll, "EnableThemeDialogTexture");
  448. uxThemeTried = 1;
  449. }
  450. return (pfnETDT) ? pfnETDT(hwnd, dwFlags) : E_NOTIMPL;
  451. }
  452. typedef BOOL(WINAPI*ISCOMPOSITIONACTIVE)(VOID);
  453. int IsAero(void)
  454. {
  455. static int uxTried = 0;
  456. static ISCOMPOSITIONACTIVE IsAeroActive = 0;
  457. if (!uxTried)
  458. {
  459. static HMODULE UXTHEME = 0;
  460. if ((UXTHEME = LoadLibraryA("uxtheme.dll")) != NULL)
  461. IsAeroActive = (ISCOMPOSITIONACTIVE)GetProcAddress(UXTHEME, "IsCompositionActive");
  462. uxTried = 1;
  463. }
  464. if (IsAeroActive)
  465. return !!IsAeroActive();
  466. else
  467. return 0;
  468. }
  469. /*
  470. int IsCharSpace(char digit)
  471. {
  472. WORD type=0;
  473. GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
  474. return type&C1_SPACE;
  475. }
  476. int IsCharSpaceW(wchar_t digit)
  477. {
  478. WORD type=0;
  479. GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
  480. return type&C1_SPACE;
  481. }
  482. */
  483. LPCWSTR BuildFullPath(LPCWSTR pszPathRoot, LPCWSTR pszPath, LPWSTR pszDest, INT cchDest)
  484. {
  485. LPCWSTR pszFile;
  486. if (!pszPath || !*pszPath)
  487. {
  488. pszDest[0] = 0x00;
  489. return pszDest;
  490. }
  491. pszFile = PathFindFileNameW(pszPath);
  492. if (pszFile != pszPath)
  493. {
  494. if (PathIsRelativeW(pszPath))
  495. {
  496. wchar_t szTemp[MAX_PATH] = {0};
  497. PathCombineW(szTemp, pszPathRoot, pszPath);
  498. PathCanonicalizeW(pszDest, szTemp);
  499. }
  500. else StringCchCopyW(pszDest, cchDest, pszPath);
  501. }
  502. else {
  503. if (pszPathRoot && *pszPathRoot) PathCombineW(pszDest, pszPathRoot, pszPath);
  504. else StringCchCopyW(pszDest, cchDest, pszPath);
  505. }
  506. return pszDest;
  507. }
  508. INT ComparePath(LPCWSTR pszPath1, LPCWSTR pszPath2, LPCWSTR pszPathRoot) // compares two pathes
  509. {
  510. INT cr;
  511. DWORD lcid;
  512. LPCWSTR pszFile1, pszFile2;
  513. if (!pszPath1 || !pszPath2) return 0;
  514. lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  515. pszFile1 = PathFindFileNameW(pszPath1);
  516. pszFile2 = PathFindFileNameW(pszPath2);
  517. cr = CompareStringW(lcid, NORM_IGNORECASE, pszFile1, -1, pszFile2, -1);
  518. if (CSTR_EQUAL == cr && (pszFile1 != pszPath1 || pszFile2 != pszPath2))
  519. {
  520. wchar_t path1[MAX_PATH*2] = {0}, path2[MAX_PATH*2] = {0};
  521. pszPath1 = BuildFullPath(pszPathRoot, pszPath1, path1, sizeof(path1)/sizeof(wchar_t));
  522. pszPath2 = BuildFullPath(pszPathRoot, pszPath2, path2, sizeof(path2)/sizeof(wchar_t));
  523. if (!pszPath1 || !pszPath2) return 0;
  524. cr = CompareStringW(lcid, NORM_IGNORECASE, pszPath1, -1, path2, -1);
  525. }
  526. return cr;
  527. }
  528. BOOL DisabledWindow_OnMouseClick(HWND hwnd)
  529. {
  530. DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
  531. if (WS_DISABLED != ((WS_CHILD | WS_DISABLED) & windowStyle))
  532. return FALSE;
  533. HWND hActive = GetActiveWindow();
  534. HWND hPopup = GetWindow(hwnd, GW_ENABLEDPOPUP);
  535. BOOL beepOk = (hPopup == hActive || hwnd == GetWindow(hActive, GW_OWNER));
  536. if (!beepOk && NULL == hPopup)
  537. {
  538. for (HWND hWalker = hwnd; ;)
  539. {
  540. hWalker = GetWindow(hWalker, GW_OWNER);
  541. if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE))))
  542. break;
  543. if (hActive == GetWindow(hWalker, GW_ENABLEDPOPUP))
  544. {
  545. beepOk = TRUE;
  546. break;
  547. }
  548. }
  549. }
  550. if (beepOk)
  551. {
  552. if (config_accessibility_modalflash.GetBool())
  553. {
  554. FLASHWINFO flashInfo;
  555. flashInfo.cbSize = sizeof(FLASHWINFO);
  556. flashInfo.hwnd = hActive;
  557. flashInfo.dwFlags = FLASHW_CAPTION;
  558. flashInfo.uCount = 2;
  559. flashInfo.dwTimeout = 100;
  560. FlashWindowEx(&flashInfo);
  561. }
  562. if (config_accessibility_modalbeep.GetBool())
  563. MessageBeep(MB_OK);
  564. }
  565. else
  566. {
  567. for (HWND hWalker = hwnd; NULL == hPopup;)
  568. {
  569. hWalker = GetWindow(hWalker, GW_OWNER);
  570. if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE))))
  571. break;
  572. hPopup = GetWindow(hWalker, GW_ENABLEDPOPUP);
  573. }
  574. SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
  575. if (NULL != hPopup && hPopup != hwnd)
  576. {
  577. BringWindowToTop(hPopup);
  578. SetActiveWindow(hPopup);
  579. }
  580. }
  581. return TRUE;
  582. }