1
0

application.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename: application.cpp
  3. ** Project: Winamp 5
  4. ** Description: Winamp's implementation of Wasabi's Application API.
  5. ** Also includes the main message loop.
  6. ** Author: Ben Allison [email protected]
  7. ** Created:
  8. **/
  9. #include "main.h"
  10. #include "application.h"
  11. #include "../nu/AutoWide.h"
  12. #include "api.h"
  13. #include "../nu/ns_wc.h"
  14. #define WIDEN2(x) L ## x
  15. #define WIDEN(x) WIDEN2(x)
  16. static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL;
  17. static ATOM DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL = 0;
  18. static BOOL DirectMouseWheel_RegisterMessage()
  19. {
  20. WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL");
  21. if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
  22. return FALSE;
  23. if (NULL != application)
  24. application->DirectMouseWheel_InitBlackList();
  25. return TRUE;
  26. }
  27. BOOL
  28. IsDirectMouseWheelMessage(const UINT uMsg)
  29. {
  30. if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
  31. {
  32. if (FALSE == DirectMouseWheel_RegisterMessage())
  33. return FALSE;
  34. }
  35. return (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg);
  36. }
  37. BOOL
  38. DirectMouseWheel_EnableConvertToMouseWheel(HWND hwnd, BOOL enable)
  39. {
  40. if (FALSE != enable)
  41. {
  42. if (0 == DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
  43. {
  44. DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL = GlobalAddAtomW(L"DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL");
  45. if (0 == DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
  46. return FALSE;
  47. }
  48. if (0 == SetPropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL), (HANDLE)1))
  49. return FALSE;
  50. }
  51. else
  52. {
  53. if (0 != DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
  54. RemovePropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL));
  55. }
  56. return TRUE;
  57. }
  58. BOOL
  59. DirectMouseWheel_IsConvertToMouseWheelEnabled(HWND hwnd)
  60. {
  61. return(0 != DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL &&
  62. NULL != GetPropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)));
  63. }
  64. Application::Application()
  65. : shuttingdown(0), activeDialog(NULL), machineID(GUID_NULL), userID(GUID_NULL), sessionID(GUID_NULL),
  66. threadStorageIndex(TLS_OUT_OF_INDEXES), messageHook(NULL), disableMessageHook(false)
  67. {
  68. tlsIndex = TlsAlloc();
  69. }
  70. Application::~Application()
  71. {
  72. if (NULL != messageHook)
  73. {
  74. UnhookWindowsHookEx(messageHook);
  75. messageHook = NULL;
  76. }
  77. }
  78. const wchar_t *Application::main_getAppName()
  79. {
  80. return WIDEN(APP_NAME);
  81. }
  82. const wchar_t *Application::main_getVersionString()
  83. {
  84. return WIDEN(APP_NAME) L" " WIDEN(APP_VERSION_STRING);
  85. }
  86. const wchar_t *Application::main_getVersionNumString()
  87. {
  88. return WIDEN(APP_VERSION);
  89. }
  90. unsigned int Application::main_getBuildNumber()
  91. {
  92. return BUILD_NUMBER;
  93. }
  94. // a guid for our app : {4BE592C7-6937-426a-A388-ACF0EBC88E93}
  95. static const GUID WinampGUID =
  96. {
  97. 0x4be592c7, 0x6937, 0x426a, { 0xa3, 0x88, 0xac, 0xf0, 0xeb, 0xc8, 0x8e, 0x93 }
  98. };
  99. GUID Application::main_getGUID()
  100. {
  101. return WinampGUID;
  102. }
  103. HANDLE Application::main_getMainThreadHandle()
  104. {
  105. if (hMainThread == 0)
  106. return (HANDLE)0;
  107. HANDLE h = (HANDLE)0;
  108. DuplicateHandle(GetCurrentProcess(), hMainThread, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS);
  109. return h;
  110. }
  111. HINSTANCE Application::main_gethInstance()
  112. {
  113. return hMainInstance;
  114. }
  115. const wchar_t *Application::main_getCommandLine()
  116. {
  117. return GetCommandLineW();
  118. }
  119. void Application::main_shutdown(int deferred)
  120. {
  121. int x = static_cast<int>(SendMessageW(hMainWindow, WM_WA_IPC, 0, IPC_IS_EXIT_ENABLED));
  122. if (!x)
  123. return;
  124. shuttingdown = 1;
  125. SendMessageW(hMainWindow, WM_CLOSE, 0, 0);
  126. }
  127. void Application::main_cancelShutdown()
  128. {
  129. shuttingdown = 0;
  130. }
  131. int Application::main_isShuttingDown()
  132. {
  133. return shuttingdown;
  134. }
  135. const wchar_t *Application::path_getAppPath()
  136. {
  137. return PROGDIR;
  138. }
  139. const wchar_t *Application::path_getUserSettingsPath()
  140. {
  141. return CONFIGDIR;
  142. }
  143. const wchar_t *Application::path_getSkinSettingsPath()
  144. {
  145. return SKINDIR;
  146. }
  147. int Application::app_getInitCount()
  148. {
  149. return 1;
  150. }
  151. void Application::app_addMessageProcessor(api_messageprocessor *processor)
  152. {
  153. messageProcessors.push_back(processor);
  154. }
  155. void Application::app_removeMessageProcessor(api_messageprocessor *processor)
  156. {
  157. //messageProcessors.eraseAll(processor);
  158. auto it = messageProcessors.begin();
  159. while (it != messageProcessors.end())
  160. {
  161. if (*it != processor)
  162. {
  163. it++;
  164. continue;
  165. }
  166. it = messageProcessors.erase(it);
  167. }
  168. }
  169. void Application::app_addModelessDialog(HWND hwnd)
  170. {
  171. OutputDebugStringA( "[Error] 'app_addModelessDialog' removed! Use 'ActiveDialog_Register' instead!\r\n" );
  172. }
  173. void Application::app_removeModelessDialog(HWND hwnd)
  174. {
  175. OutputDebugStringA( "[Error] 'app_removeModelessDialog' removed!Use 'ActiveDialog_Unregister' instead!\r\n" );
  176. }
  177. void Application::app_addAccelerators(HWND hwnd, HACCEL *phAccel, INT cAccel, UINT translateMode)
  178. {
  179. AccelMap::iterator accelIterator;
  180. ACCELNODE *pList;
  181. if (accelerators.size() > 0)
  182. {
  183. accelIterator = accelerators.end();
  184. do
  185. {
  186. accelIterator--;
  187. if (!IsWindow(accelIterator->first))
  188. {
  189. //app_removeAccelerators(accelIterator->first);
  190. ACCELNODE* pList, * pNode;
  191. pList = accelIterator->second;
  192. while (pList)
  193. {
  194. pNode = pList;
  195. pList = (pList->pNext) ? pList->pNext : NULL;
  196. free(pNode);
  197. }
  198. accelIterator = accelerators.erase(accelIterator);
  199. }
  200. } while (accelIterator != accelerators.begin() && accelIterator != accelerators.end());
  201. }
  202. if (!IsWindow(hwnd) || !phAccel || cAccel <= 0) return;
  203. accelIterator = accelerators.find(hwnd);
  204. if(accelIterator != accelerators.end())
  205. pList = accelIterator->second;
  206. else
  207. {
  208. pList = (ACCELNODE*)calloc(1, sizeof(ACCELNODE));
  209. if(pList)
  210. {
  211. accelerators.insert({hwnd, pList});
  212. }
  213. }
  214. if (!pList) return;
  215. while (pList->pNext) pList = pList->pNext;
  216. while(cAccel--)
  217. {
  218. if (*phAccel)
  219. {
  220. ACCELNODE *pNode;
  221. if (pList->hAccel)
  222. {
  223. pNode = (ACCELNODE*)calloc(1, sizeof(ACCELNODE));
  224. pNode->pNext = NULL;
  225. pList->pNext = pNode;
  226. pList = pNode;
  227. }
  228. else pNode = pList;
  229. pNode->hAccel = *phAccel;
  230. pNode->translateMode = translateMode;
  231. }
  232. phAccel++;
  233. }
  234. }
  235. void Application::app_removeAccelerators(HWND hwnd)
  236. {
  237. AccelMap::iterator iter = accelerators.find(hwnd);
  238. if(iter == accelerators.end())
  239. return;
  240. ACCELNODE *pList, *pNode;
  241. pList = iter->second;
  242. while(pList)
  243. {
  244. pNode = pList;
  245. pList = (pList->pNext) ? pList->pNext : NULL;
  246. free(pNode);
  247. }
  248. accelerators.erase(hwnd);
  249. }
  250. int Application::app_getAccelerators(HWND hwnd, HACCEL *phAccel, INT cchAccelMax, BOOL bGlobal)
  251. {
  252. if (!hwnd || 0 == accelerators.size()) return 0;
  253. if ((!phAccel && cchAccelMax) || (phAccel && !cchAccelMax)) return 0;
  254. AccelMap::iterator accelIterator = accelerators.end();
  255. INT count = 0;
  256. do
  257. {
  258. accelIterator--;
  259. for (ACCELNODE *pNode = accelIterator->second; NULL != pNode; pNode = pNode->pNext)
  260. {
  261. if (accelIterator->first == hwnd ||
  262. (bGlobal && (TRANSLATE_MODE_GLOBAL == pNode->translateMode ||
  263. (TRANSLATE_MODE_CHILD == pNode->translateMode && IsChild(accelIterator->first, hwnd)))))
  264. {
  265. if (phAccel && cchAccelMax)
  266. {
  267. *phAccel = pNode->hAccel;
  268. phAccel++;
  269. cchAccelMax--;
  270. }
  271. count++;
  272. }
  273. }
  274. }
  275. while (accelIterator != accelerators.begin() && (!phAccel || cchAccelMax));
  276. return count;
  277. }
  278. void Application::app_registerGlobalWindow(HWND hwnd)
  279. {
  280. for (std::vector<HWND>::const_iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
  281. {
  282. if (*e == hwnd) return;
  283. }
  284. globalWindows.push_back(hwnd);
  285. }
  286. void Application::app_unregisterGlobalWindow(HWND hwnd)
  287. {
  288. for (std::vector<HWND>::iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
  289. {
  290. if (*e == hwnd)
  291. {
  292. globalWindows.erase(e);
  293. return;
  294. }
  295. }
  296. }
  297. bool Application::FilterMessage(MSG *msg) // returns 1 if you should Dispatch the message, will handle TranslateMessage for you
  298. {
  299. if (msg->hwnd != NULL && msg->hwnd != hMainWindow && msg->hwnd != hEQWindow // && msg.hwnd != hMBWindow
  300. && msg->hwnd != hPLWindow && msg->hwnd != hVideoWindow)
  301. {
  302. HWND hWndParent = NULL;
  303. HWND temphwnd = msg->hwnd;
  304. if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
  305. hWndParent = temphwnd;
  306. /*while (*/temphwnd = GetParent(temphwnd)/*)*/ ;
  307. {
  308. if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
  309. hWndParent = temphwnd;
  310. }
  311. if (NULL != hWndParent)
  312. {
  313. BOOL processed;
  314. disableMessageHook = true;
  315. processed = IsDialogMessageW(hWndParent, msg);
  316. disableMessageHook = false;
  317. if (FALSE != processed)
  318. return true;
  319. }
  320. //if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ||
  321. // msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
  322. //{
  323. //if (IsChild(hMBWindow,msg.hwnd) && TranslateAccelerator(hMBWindow,hAccel[3],&msg)) continue;
  324. TranslateMessage(msg);
  325. //}
  326. }
  327. return false;
  328. }
  329. bool Application::isGlobalWindow(HWND hwnd)
  330. {
  331. for (std::vector<HWND>::const_iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
  332. {
  333. if (*e == hwnd || IsChild(*e, hwnd)) return true;
  334. }
  335. return false;
  336. }
  337. bool Application::app_translateAccelerators(MSG *msg)
  338. {
  339. if (accelerators.size() > 0)
  340. {
  341. AccelMap::iterator accelIterator = accelerators.end();
  342. do
  343. {
  344. accelIterator--;
  345. for (ACCELNODE *pNode = accelIterator->second; NULL != pNode; pNode = pNode->pNext)
  346. {
  347. if (((TRANSLATE_MODE_GLOBAL == pNode->translateMode && isGlobalWindow(msg->hwnd)) ||
  348. accelIterator->first == msg->hwnd ||
  349. (TRANSLATE_MODE_CHILD == pNode->translateMode && IsChild(accelIterator->first, msg->hwnd))) &&
  350. TranslateAcceleratorW(accelIterator->first, pNode->hAccel, msg))
  351. {
  352. return true;
  353. }
  354. }
  355. }
  356. while (accelIterator != accelerators.begin());
  357. }
  358. return false;
  359. }
  360. bool
  361. Application::DirectMouseWheel_RegisterSkipClass(ATOM klass)
  362. {
  363. size_t index;
  364. if (klass < 0xC000)
  365. return false;
  366. index = directMouseWheelBlackList.size();
  367. while(index--)
  368. {
  369. if (directMouseWheelBlackList[index] == klass)
  370. return false;
  371. }
  372. directMouseWheelBlackList.push_back(klass);
  373. return true;
  374. }
  375. bool
  376. Application::DirectMouseWheel_UnregisterSkipClass(ATOM klass)
  377. {
  378. size_t index;
  379. if (klass < 0xC000)
  380. return false;
  381. index = directMouseWheelBlackList.size();
  382. while(index--)
  383. {
  384. if (directMouseWheelBlackList[index] == klass)
  385. {
  386. directMouseWheelBlackList.erase(directMouseWheelBlackList.begin() + index);
  387. return true;
  388. }
  389. }
  390. return false;
  391. }
  392. bool
  393. Application::DirectMouseWheel_EnableConvertToMouseWheel(HWND hwnd, BOOL enable)
  394. {
  395. return (0 != ::DirectMouseWheel_EnableConvertToMouseWheel(hwnd, enable));
  396. }
  397. void
  398. Application::DirectMouseWheel_InitBlackList()
  399. {
  400. size_t index;
  401. WNDCLASSW klassInfo;
  402. ATOM klassAtom;
  403. const static LPCWSTR defaultBlackListNames[] =
  404. {
  405. L"msctls_trackbar32",
  406. L"msctls_updown32",
  407. L"SysHeader32",
  408. };
  409. const static ATOM defaultBlackListAtoms[] =
  410. {
  411. 0xC017, // button
  412. 0xC018, // edit
  413. 0xC019, // static
  414. 0xC01C, // combobox
  415. };
  416. for (index = 0; index < ARRAYSIZE(defaultBlackListAtoms); index++)
  417. {
  418. directMouseWheelBlackList.push_back(defaultBlackListAtoms[index]);
  419. }
  420. for (index = 0; index < ARRAYSIZE(defaultBlackListNames); index++)
  421. {
  422. klassAtom = (ATOM)GetClassInfoW(NULL, defaultBlackListNames[index], &klassInfo);
  423. if (0 != klassAtom)
  424. directMouseWheelBlackList.push_back(klassAtom);
  425. }
  426. }
  427. bool
  428. Application::DirectMouseWheel_ProccessMessage(MSG *msg)
  429. {
  430. HWND targetWindow;
  431. ATOM targetAtom;
  432. DWORD targetProcessId;
  433. POINT mousePoint;
  434. size_t index, listSize;
  435. if (msg->message != WM_MOUSEWHEEL)
  436. return false;
  437. if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
  438. {
  439. if (FALSE == DirectMouseWheel_RegisterMessage())
  440. return false;
  441. }
  442. POINTSTOPOINT(mousePoint, msg->lParam);
  443. targetWindow = WindowFromPoint(mousePoint);
  444. if (NULL == targetWindow || targetWindow == msg->hwnd)
  445. return false;
  446. GetWindowThreadProcessId(targetWindow, &targetProcessId);
  447. if (targetProcessId != GetCurrentProcessId())
  448. return false;
  449. if (FALSE == IsWindowEnabled(targetWindow))
  450. return false;
  451. listSize = directMouseWheelBlackList.size();
  452. index = 0;
  453. while(index != listSize)
  454. {
  455. targetAtom = (ATOM)GetClassLongPtrW(targetWindow, GCW_ATOM);
  456. for(index = 0; index < listSize; index++)
  457. {
  458. if (targetAtom == directMouseWheelBlackList[index])
  459. {
  460. targetWindow = GetAncestor(targetWindow, GA_PARENT);
  461. if (NULL == targetWindow || targetWindow == msg->hwnd)
  462. return false;
  463. break;
  464. }
  465. }
  466. }
  467. if (FALSE != DirectMouseWheel_IsConvertToMouseWheelEnabled(targetWindow))
  468. {
  469. SendMessageW(targetWindow, WM_MOUSEWHEEL, msg->wParam, msg->lParam);
  470. return true;
  471. }
  472. else if (0 != SendMessageW(targetWindow, WINAMP_WM_DIRECT_MOUSE_WHEEL, msg->wParam, msg->lParam))
  473. return true;
  474. return false;
  475. }
  476. HWND ActiveChildWindowFromPoint( HWND hwnd, POINTS cursor_s, const int *controls, size_t controlsCount )
  477. {
  478. POINT pt;
  479. RECT controlRect;
  480. HWND controlWindow;
  481. POINTSTOPOINT( pt, cursor_s );
  482. while ( controlsCount-- )
  483. {
  484. controlWindow = GetDlgItem( hwnd, controls[ controlsCount ] );
  485. if ( controlWindow != NULL && GetClientRect( controlWindow, &controlRect ) != FALSE )
  486. {
  487. MapWindowPoints( controlWindow, HWND_DESKTOP, (POINT *) &controlRect, 2 );
  488. if ( PtInRect( &controlRect, pt ) != FALSE )
  489. {
  490. unsigned long windowStyle = (unsigned long) GetWindowLongPtrW( controlWindow, GWL_STYLE );
  491. if ( ( ( WS_VISIBLE | WS_DISABLED ) & windowStyle ) == WS_VISIBLE )
  492. return controlWindow;
  493. break;
  494. }
  495. }
  496. }
  497. return NULL;
  498. }
  499. BOOL DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam, const int controls[], int controlslen)
  500. {
  501. if (FALSE != ::IsDirectMouseWheelMessage(uMsg))
  502. {
  503. HWND targetWindow = ::ActiveChildWindowFromPoint(hwnd, MAKEPOINTS(lParam), controls, controlslen);
  504. if (NULL != targetWindow)
  505. {
  506. SendMessageW(targetWindow, WM_MOUSEWHEEL, wParam, lParam);
  507. SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (long)TRUE);
  508. return TRUE;
  509. }
  510. }
  511. return FALSE;
  512. }
  513. BOOL Application::DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam, const int controls[], int controlslen)
  514. {
  515. return ::DirectMouseWheel_ProcessDialogMessage(hwnd, uMsg, wParam, lParam, controls, controlslen);
  516. }
  517. void Application::ActiveDialog_Register(HWND hwnd)
  518. {
  519. activeDialog = hwnd;
  520. }
  521. void Application::ActiveDialog_Unregister(HWND hwnd)
  522. {
  523. if (hwnd == activeDialog)
  524. activeDialog = NULL;
  525. }
  526. HWND Application::ActiveDialog_Get()
  527. {
  528. return activeDialog;
  529. }
  530. /* Plugins can register a 'Message Processor' to tap into the main message loop
  531. for some purposes (Dialog message handling, ActiveX/ATL/COM, wxWidgets)
  532. this is the only way to make sure all messages are processed correctly
  533. @see api_application::app_addMessageProcessor() and api_messageprocessor.h
  534. */
  535. bool Application::ProcessMessageLight( MSG *msg )
  536. {
  537. /* messageProcessors is the list of registered Message Processors */
  538. for ( api_messageprocessor *processor : messageProcessors )
  539. {
  540. disableMessageHook = true;
  541. if ( processor->ProcessMessage( msg ) ) // it'll return true if it wants to eat the message
  542. {
  543. disableMessageHook = false;
  544. return true;
  545. }
  546. }
  547. disableMessageHook = false;
  548. if ( false != DirectMouseWheel_ProccessMessage( msg ) )
  549. return true;
  550. return false;
  551. }
  552. bool Application::ProcessMessage( MSG *msg )
  553. {
  554. if ( ProcessMessageLight( msg ) != false )
  555. return true;
  556. if ( ( msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ) && app_translateAccelerators( msg ) )
  557. return true;
  558. if ( activeDialog != NULL )
  559. {
  560. disableMessageHook = true;
  561. if ( IsDialogMessageW( activeDialog, msg ) != FALSE )
  562. {
  563. disableMessageHook = false;
  564. return true;
  565. }
  566. }
  567. disableMessageHook = false;
  568. return false;
  569. }
  570. intptr_t Application::app_messageLoopStep()
  571. {
  572. MSG msg;
  573. if (PeekMessageW(&msg, NULL, 0, 0, TRUE))
  574. {
  575. if (msg.message == WM_QUIT)
  576. {
  577. PostQuitMessage((int)msg.wParam);
  578. return msg.wParam ; // abandoned due to WM_QUIT
  579. }
  580. if (!ProcessMessage(&msg) && !FilterMessage(&msg))
  581. DispatchMessageW(&msg);
  582. if (WM_NCDESTROY == msg.message)
  583. DirectMouseWheel_EnableConvertToMouseWheel(msg.hwnd, FALSE);
  584. return msg.wParam;
  585. }
  586. return 0;
  587. }
  588. LRESULT CALLBACK Application::MessageHookProc( INT code, WPARAM wParam, LPARAM lParam )
  589. {
  590. if ( application == NULL || application->messageHook == NULL )
  591. {
  592. return FALSE;
  593. }
  594. if ( application->disableMessageHook == false )
  595. {
  596. switch ( code )
  597. {
  598. case MSGF_DIALOGBOX:
  599. case MSGF_MESSAGEBOX:
  600. if ( false != application->ProcessMessageLight( (MSG *) lParam ) )
  601. return 1;
  602. break;
  603. }
  604. }
  605. else
  606. application->disableMessageHook = false;
  607. return CallNextHookEx( application->messageHook, code, wParam, lParam );
  608. }
  609. WPARAM Application::MessageLoop()
  610. {
  611. if ( messageHook == NULL )
  612. messageHook = SetWindowsHookEx( WH_MSGFILTER, MessageHookProc, NULL, GetCurrentThreadId() );
  613. for ( ;;)
  614. {
  615. DWORD dwStatus = MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE );
  616. if ( dwStatus == WAIT_OBJECT_0 )
  617. {
  618. MSG msg;
  619. while ( PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ) )
  620. {
  621. if ( msg.message == WM_QUIT )
  622. return msg.wParam;
  623. if ( !ProcessMessage( &msg ) && !FilterMessage( &msg ) )
  624. DispatchMessageW( &msg );
  625. }
  626. }
  627. }
  628. }
  629. WPARAM WinampMessageLoop()
  630. {
  631. return WASABI_API_APP->MessageLoop();
  632. }
  633. const wchar_t *Application::path_getWorkingPath()
  634. {
  635. return config_cwd;
  636. }
  637. void Application::path_setWorkingPath(const wchar_t *newPath)
  638. {
  639. StringCchCopyW(config_cwd, MAX_PATH, newPath);
  640. }
  641. /*
  642. int Application::GetMachineID(GUID *id)
  643. {
  644. // TODO: stuff this in the registry
  645. if (machineID == GUID_NULL)
  646. {
  647. if (!GetPrivateProfileStruct(app_name, "mid", (LPVOID)&machineID, sizeof(machineID), INI_FILE) || machineID == GUID_NULL)
  648. {
  649. UuidCreate(&machineID);
  650. WritePrivateProfileStruct(app_name, "mid", (LPVOID)&machineID, sizeof(machineID), INI_FILE);
  651. }
  652. }
  653. *id = machineID;
  654. return API_APPLICATION_SUCCESS;
  655. }
  656. */
  657. int Application::GetUserID(GUID *id)
  658. {
  659. if (userID == GUID_NULL)
  660. {
  661. config_uid_ft = (char)GetPrivateProfileIntW(L"Winamp", L"uid_ft", 0, INI_FILE);
  662. wchar_t uid_str[512] = {0};
  663. if (!GetPrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA) || userID == GUID_NULL)
  664. {
  665. // attempt to restore the client uid after an uninstall, lost config file, etc
  666. readwrite_client_uid(0, uid_str);
  667. if (uid_str[0])
  668. {
  669. WritePrivateProfileStringW(AutoWide(app_name), L"uid", uid_str, INI_FILE);
  670. }
  671. if (!GetPrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA) || userID == GUID_NULL)
  672. {
  673. UuidCreate(&userID);
  674. WritePrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA);
  675. GetPrivateProfileStringW(AutoWide(app_name), L"uid", L"", uid_str, ARRAYSIZE(uid_str), INI_FILE);
  676. readwrite_client_uid(1, uid_str);
  677. // if done then no need to re-do it at a later point
  678. config_uid_ft = 1;
  679. }
  680. }
  681. // and just to make sure, if this is like a new run then we'll need to force into the registry
  682. if (!config_uid_ft)
  683. {
  684. config_uid_ft = 1;
  685. GetPrivateProfileStringW(AutoWide(app_name), L"uid", L"", uid_str, ARRAYSIZE(uid_str), INI_FILE);
  686. readwrite_client_uid(1, uid_str);
  687. }
  688. }
  689. *id = userID;
  690. return API_APPLICATION_SUCCESS;
  691. }
  692. int Application::GetSessionID(GUID *id)
  693. {
  694. if (sessionID == GUID_NULL)
  695. UuidCreate(&sessionID);
  696. *id = sessionID;
  697. return API_APPLICATION_SUCCESS;
  698. }
  699. size_t Application::AllocateThreadStorage()
  700. {
  701. return (size_t)InterlockedIncrement(&threadStorageIndex);
  702. }
  703. void *Application::GetThreadStorage(size_t index)
  704. {
  705. std::vector<void*> *ptrlist = (std::vector<void*> *)TlsGetValue(tlsIndex);
  706. if (!ptrlist)
  707. return 0;
  708. if ((index+1) > ptrlist->size())
  709. return 0;
  710. return ptrlist->at(index);
  711. }
  712. void Application::SetThreadStorage(size_t index, void *value)
  713. {
  714. std::vector<void*> *ptrlist = (std::vector<void*> *)TlsGetValue(tlsIndex);
  715. if (!ptrlist)
  716. {
  717. ptrlist = new std::vector<void*>;
  718. TlsSetValue(tlsIndex, ptrlist);
  719. }
  720. size_t ptrlist_size = ptrlist->size();
  721. if ((index+1) > ptrlist_size)
  722. {
  723. ptrlist->reserve(index+1);
  724. for (size_t i=ptrlist_size;i<=index;i++)
  725. {
  726. ptrlist->push_back(0);
  727. }
  728. }
  729. ptrlist->at(index) = value;
  730. }
  731. const wchar_t *Application::getATFString()
  732. {
  733. return config_titlefmt;
  734. }
  735. int Application::getScaleX(int x)
  736. {
  737. return ScaleX(x);
  738. }
  739. int Application::getScaleY(int y)
  740. {
  741. return ScaleY(y);
  742. }
  743. #define CBCLASS Application
  744. START_DISPATCH;
  745. CB(API_APPLICATION_MAIN_GETAPPNAME, main_getAppName)
  746. CB(API_APPLICATION_MAIN_GETVERSIONSTRING, main_getVersionString)
  747. CB(API_APPLICATION_MAIN_GETVERSIONSTRING2, main_getVersionNumString)
  748. CB(API_APPLICATION_MAIN_GETBUILDNUMBER, main_getBuildNumber)
  749. CB(API_APPLICATION_MAIN_GETGUID, main_getGUID)
  750. CB(API_APPLICATION_MAIN_GETMAINTHREADHANDLE, main_getMainThreadHandle)
  751. CB(API_APPLICATION_MAIN_GETHINSTANCE, main_gethInstance)
  752. CB(API_APPLICATION_MAIN_GETCOMMANDLINE, main_getCommandLine)
  753. VCB(API_APPLICATION_MAIN_SHUTDOWN, main_shutdown)
  754. VCB(API_APPLICATION_MAIN_CANCELSHUTDOWN, main_cancelShutdown)
  755. CB(API_APPLICATION_MAIN_ISSHUTTINGDOWN, main_isShuttingDown)
  756. CB(API_APPLICATION_PATH_GETAPPPATH, path_getAppPath)
  757. CB(API_APPLICATION_PATH_GETUSERSETTINGSPATH, path_getUserSettingsPath)
  758. CB(API_APPLICATION_PATH_GETSKINSETTINGSPATH, path_getSkinSettingsPath)
  759. CB(API_APPLICATION_APP_GETINITCOUNT, app_getInitCount)
  760. CB(API_APPLICATION_APP_MESSAGELOOPSTEP, app_messageLoopStep)
  761. VCB(API_APPLICATION_APP_ADDMESSAGEPROCESSOR, app_addMessageProcessor)
  762. VCB(API_APPLICATION_APP_REMOVEMESSAGEPROCESSOR, app_removeMessageProcessor)
  763. VCB(API_APPLICATION_APP_ADDMODELESSDIALOG, app_addModelessDialog)
  764. VCB(API_APPLICATION_APP_REMOVEMODELESSDIALOG, app_removeModelessDialog)
  765. VCB(API_APPLICATION_APP_ADDACCELERATORS, app_addAccelerators)
  766. VCB(API_APPLICATION_APP_REMOVEACCELERATORS, app_removeAccelerators)
  767. CB(API_APPLICATION_APP_TRANSLATEACCELERATORS, app_translateAccelerators);
  768. CB(API_APPLICATION_APP_GETACCELERATORS, app_getAccelerators);
  769. VCB(API_APPLICATION_APP_REGISTERGLOBALWINDOW, app_registerGlobalWindow);
  770. VCB(API_APPLICATION_APP_UNREGISTERGLOBALWINDOW, app_unregisterGlobalWindow);
  771. CB(API_APPLICATION_PATH_GETWORKINGPATH, path_getWorkingPath);
  772. VCB(API_APPLICATION_PATH_SETWORKINGPATH, path_setWorkingPath);
  773. CB(API_APPLICATION_DIRECTMOUSEWHEEL_REGISTERSKIPCLASS, DirectMouseWheel_RegisterSkipClass);
  774. CB(API_APPLICATION_DIRECTMOUSEWHEEL_UNREGISTERSKIPCLASS, DirectMouseWheel_UnregisterSkipClass);
  775. CB(API_APPLICATION_DIRECTMOUSEWHEEL_ENABLECONVERTTOMOUSEWHEEL, DirectMouseWheel_EnableConvertToMouseWheel);
  776. CB(API_APPLICATION_DIRECTMOUSEWHEEL_PROCESSDIALOGMESSAGE, DirectMouseWheel_ProcessDialogMessage);
  777. VCB(API_APPLICATION_ACTIVEDIALOG_REGISTER, ActiveDialog_Register);
  778. VCB(API_APPLICATION_ACTIVEDIALOG_UNREGISTER, ActiveDialog_Unregister);
  779. CB(API_APPLICATION_ACTIVEDIALOG_GET, ActiveDialog_Get);
  780. /*
  781. CB(API_APPLICATION_GETMACHINEID, GetMachineID);
  782. */
  783. CB(API_APPLICATION_GETUSERID, GetUserID);
  784. CB(API_APPLICATION_GETSESSIONID, GetSessionID);
  785. CB(API_APPLICATION_ALLOCATETHREADSTORAGE, AllocateThreadStorage);
  786. CB(API_APPLICATION_GETTHREADSTORAGE, GetThreadStorage);
  787. VCB(API_APPLICATION_SETTHREADSTORAGE, SetThreadStorage);
  788. CB(API_APPLICATION_GETATFSTRING, getATFString);
  789. CB(API_APPLICATION_GETSCALEX, getScaleX);
  790. CB(API_APPLICATION_GETSCALEY, getScaleY);
  791. END_DISPATCH;
  792. #undef CBCLASS