aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/application.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/application.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/application.cpp')
-rw-r--r--Src/Winamp/application.cpp941
1 files changed, 941 insertions, 0 deletions
diff --git a/Src/Winamp/application.cpp b/Src/Winamp/application.cpp
new file mode 100644
index 00000000..b7b6ca34
--- /dev/null
+++ b/Src/Winamp/application.cpp
@@ -0,0 +1,941 @@
+/** (c) Nullsoft, Inc. C O N F I D E N T I A L
+ ** Filename: application.cpp
+ ** Project: Winamp 5
+ ** Description: Winamp's implementation of Wasabi's Application API.
+ ** Also includes the main message loop.
+ ** Author: Ben Allison benski@nullsoft.com
+ ** Created:
+ **/
+#include "main.h"
+#include "application.h"
+#include "../nu/AutoWide.h"
+#include "api.h"
+#include "../nu/ns_wc.h"
+
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+
+static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL;
+static ATOM DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL = 0;
+
+static BOOL DirectMouseWheel_RegisterMessage()
+{
+ WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL");
+ if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
+ return FALSE;
+
+ if (NULL != application)
+ application->DirectMouseWheel_InitBlackList();
+
+ return TRUE;
+}
+
+BOOL
+IsDirectMouseWheelMessage(const UINT uMsg)
+{
+ if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
+ {
+ if (FALSE == DirectMouseWheel_RegisterMessage())
+ return FALSE;
+ }
+
+ return (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg);
+}
+
+BOOL
+DirectMouseWheel_EnableConvertToMouseWheel(HWND hwnd, BOOL enable)
+{
+ if (FALSE != enable)
+ {
+ if (0 == DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
+ {
+ DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL = GlobalAddAtomW(L"DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL");
+ if (0 == DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
+ return FALSE;
+ }
+
+ if (0 == SetPropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL), (HANDLE)1))
+ return FALSE;
+ }
+ else
+ {
+ if (0 != DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)
+ RemovePropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL));
+ }
+
+ return TRUE;
+}
+
+BOOL
+DirectMouseWheel_IsConvertToMouseWheelEnabled(HWND hwnd)
+{
+ return(0 != DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL &&
+ NULL != GetPropW(hwnd, (const wchar_t*)MAKEINTATOM(DIRECT_MOUSE_WHEEL_CONVERT_TO_MOUSE_WHEEL)));
+}
+
+Application::Application()
+ : shuttingdown(0), activeDialog(NULL), machineID(GUID_NULL), userID(GUID_NULL), sessionID(GUID_NULL),
+ threadStorageIndex(TLS_OUT_OF_INDEXES), messageHook(NULL), disableMessageHook(false)
+{
+ tlsIndex = TlsAlloc();
+}
+
+Application::~Application()
+{
+ if (NULL != messageHook)
+ {
+ UnhookWindowsHookEx(messageHook);
+ messageHook = NULL;
+ }
+}
+
+const wchar_t *Application::main_getAppName()
+{
+ return WIDEN(APP_NAME);
+}
+
+const wchar_t *Application::main_getVersionString()
+{
+ return WIDEN(APP_NAME) L" " WIDEN(APP_VERSION_STRING);
+}
+
+const wchar_t *Application::main_getVersionNumString()
+{
+ return WIDEN(APP_VERSION);
+}
+
+unsigned int Application::main_getBuildNumber()
+{
+ return BUILD_NUMBER;
+}
+
+// a guid for our app : {4BE592C7-6937-426a-A388-ACF0EBC88E93}
+static const GUID WinampGUID =
+ {
+ 0x4be592c7, 0x6937, 0x426a, { 0xa3, 0x88, 0xac, 0xf0, 0xeb, 0xc8, 0x8e, 0x93 }
+ };
+
+GUID Application::main_getGUID()
+{
+ return WinampGUID;
+}
+
+HANDLE Application::main_getMainThreadHandle()
+{
+ if (hMainThread == 0)
+ return (HANDLE)0;
+ HANDLE h = (HANDLE)0;
+ DuplicateHandle(GetCurrentProcess(), hMainThread, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ return h;
+}
+
+HINSTANCE Application::main_gethInstance()
+{
+ return hMainInstance;
+}
+
+const wchar_t *Application::main_getCommandLine()
+{
+ return GetCommandLineW();
+}
+
+void Application::main_shutdown(int deferred)
+{
+
+ int x = static_cast<int>(SendMessageW(hMainWindow, WM_WA_IPC, 0, IPC_IS_EXIT_ENABLED));
+
+ if (!x)
+ return;
+
+ shuttingdown = 1;
+
+ SendMessageW(hMainWindow, WM_CLOSE, 0, 0);
+}
+
+void Application::main_cancelShutdown()
+{
+ shuttingdown = 0;
+}
+
+int Application::main_isShuttingDown()
+{
+ return shuttingdown;
+}
+
+const wchar_t *Application::path_getAppPath()
+{
+ return PROGDIR;
+}
+
+const wchar_t *Application::path_getUserSettingsPath()
+{
+ return CONFIGDIR;
+}
+
+const wchar_t *Application::path_getSkinSettingsPath()
+{
+ return SKINDIR;
+}
+
+int Application::app_getInitCount()
+{
+ return 1;
+}
+
+void Application::app_addMessageProcessor(api_messageprocessor *processor)
+{
+ messageProcessors.push_back(processor);
+}
+
+void Application::app_removeMessageProcessor(api_messageprocessor *processor)
+{
+ //messageProcessors.eraseAll(processor);
+ auto it = messageProcessors.begin();
+ while (it != messageProcessors.end())
+ {
+ if (*it != processor)
+ {
+ it++;
+ continue;
+ }
+
+ it = messageProcessors.erase(it);
+ }
+}
+
+void Application::app_addModelessDialog(HWND hwnd)
+{
+ OutputDebugStringA( "[Error] 'app_addModelessDialog' removed! Use 'ActiveDialog_Register' instead!\r\n" );
+}
+
+void Application::app_removeModelessDialog(HWND hwnd)
+{
+ OutputDebugStringA( "[Error] 'app_removeModelessDialog' removed!Use 'ActiveDialog_Unregister' instead!\r\n" );
+}
+
+void Application::app_addAccelerators(HWND hwnd, HACCEL *phAccel, INT cAccel, UINT translateMode)
+{
+ AccelMap::iterator accelIterator;
+ ACCELNODE *pList;
+
+ if (accelerators.size() > 0)
+ {
+ accelIterator = accelerators.end();
+ do
+ {
+ accelIterator--;
+ if (!IsWindow(accelIterator->first))
+ {
+ //app_removeAccelerators(accelIterator->first);
+ ACCELNODE* pList, * pNode;
+ pList = accelIterator->second;
+ while (pList)
+ {
+ pNode = pList;
+ pList = (pList->pNext) ? pList->pNext : NULL;
+ free(pNode);
+ }
+ accelIterator = accelerators.erase(accelIterator);
+ }
+ } while (accelIterator != accelerators.begin() && accelIterator != accelerators.end());
+ }
+
+ if (!IsWindow(hwnd) || !phAccel || cAccel <= 0) return;
+
+ accelIterator = accelerators.find(hwnd);
+ if(accelIterator != accelerators.end())
+ pList = accelIterator->second;
+ else
+ {
+ pList = (ACCELNODE*)calloc(1, sizeof(ACCELNODE));
+ if(pList)
+ {
+ accelerators.insert({hwnd, pList});
+ }
+ }
+ if (!pList) return;
+ while (pList->pNext) pList = pList->pNext;
+
+ while(cAccel--)
+ {
+ if (*phAccel)
+ {
+ ACCELNODE *pNode;
+ if (pList->hAccel)
+ {
+ pNode = (ACCELNODE*)calloc(1, sizeof(ACCELNODE));
+ pNode->pNext = NULL;
+ pList->pNext = pNode;
+ pList = pNode;
+ }
+ else pNode = pList;
+
+ pNode->hAccel = *phAccel;
+ pNode->translateMode = translateMode;
+
+ }
+ phAccel++;
+ }
+}
+
+void Application::app_removeAccelerators(HWND hwnd)
+{
+ AccelMap::iterator iter = accelerators.find(hwnd);
+ if(iter == accelerators.end())
+ return;
+
+ ACCELNODE *pList, *pNode;
+ pList = iter->second;
+ while(pList)
+ {
+ pNode = pList;
+ pList = (pList->pNext) ? pList->pNext : NULL;
+ free(pNode);
+ }
+ accelerators.erase(hwnd);
+}
+
+int Application::app_getAccelerators(HWND hwnd, HACCEL *phAccel, INT cchAccelMax, BOOL bGlobal)
+{
+
+ if (!hwnd || 0 == accelerators.size()) return 0;
+ if ((!phAccel && cchAccelMax) || (phAccel && !cchAccelMax)) return 0;
+
+ AccelMap::iterator accelIterator = accelerators.end();
+ INT count = 0;
+
+ do
+ {
+ accelIterator--;
+ for (ACCELNODE *pNode = accelIterator->second; NULL != pNode; pNode = pNode->pNext)
+ {
+ if (accelIterator->first == hwnd ||
+ (bGlobal && (TRANSLATE_MODE_GLOBAL == pNode->translateMode ||
+ (TRANSLATE_MODE_CHILD == pNode->translateMode && IsChild(accelIterator->first, hwnd)))))
+ {
+ if (phAccel && cchAccelMax)
+ {
+ *phAccel = pNode->hAccel;
+ phAccel++;
+ cchAccelMax--;
+ }
+ count++;
+ }
+ }
+ }
+ while (accelIterator != accelerators.begin() && (!phAccel || cchAccelMax));
+
+ return count;
+}
+
+void Application::app_registerGlobalWindow(HWND hwnd)
+{
+ for (std::vector<HWND>::const_iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
+ {
+ if (*e == hwnd) return;
+ }
+ globalWindows.push_back(hwnd);
+}
+
+void Application::app_unregisterGlobalWindow(HWND hwnd)
+{
+ for (std::vector<HWND>::iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
+ {
+ if (*e == hwnd)
+ {
+ globalWindows.erase(e);
+ return;
+ }
+ }
+
+}
+
+bool Application::FilterMessage(MSG *msg) // returns 1 if you should Dispatch the message, will handle TranslateMessage for you
+{
+ if (msg->hwnd != NULL && msg->hwnd != hMainWindow && msg->hwnd != hEQWindow // && msg.hwnd != hMBWindow
+ && msg->hwnd != hPLWindow && msg->hwnd != hVideoWindow)
+ {
+ HWND hWndParent = NULL;
+ HWND temphwnd = msg->hwnd;
+ if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
+ hWndParent = temphwnd;
+
+ /*while (*/temphwnd = GetParent(temphwnd)/*)*/ ;
+ {
+ if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
+ hWndParent = temphwnd;
+ }
+
+ if (NULL != hWndParent)
+ {
+ BOOL processed;
+
+ disableMessageHook = true;
+ processed = IsDialogMessageW(hWndParent, msg);
+ disableMessageHook = false;
+
+ if (FALSE != processed)
+ return true;
+ }
+
+ //if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ||
+ // msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
+ //{
+ //if (IsChild(hMBWindow,msg.hwnd) && TranslateAccelerator(hMBWindow,hAccel[3],&msg)) continue;
+ TranslateMessage(msg);
+ //}
+ }
+ return false;
+}
+bool Application::isGlobalWindow(HWND hwnd)
+{
+ for (std::vector<HWND>::const_iterator e = globalWindows.begin(); e != globalWindows.end(); e++)
+ {
+ if (*e == hwnd || IsChild(*e, hwnd)) return true;
+ }
+ return false;
+}
+
+bool Application::app_translateAccelerators(MSG *msg)
+{
+ if (accelerators.size() > 0)
+ {
+ AccelMap::iterator accelIterator = accelerators.end();
+ do
+ {
+ accelIterator--;
+ for (ACCELNODE *pNode = accelIterator->second; NULL != pNode; pNode = pNode->pNext)
+ {
+ if (((TRANSLATE_MODE_GLOBAL == pNode->translateMode && isGlobalWindow(msg->hwnd)) ||
+ accelIterator->first == msg->hwnd ||
+ (TRANSLATE_MODE_CHILD == pNode->translateMode && IsChild(accelIterator->first, msg->hwnd))) &&
+ TranslateAcceleratorW(accelIterator->first, pNode->hAccel, msg))
+ {
+ return true;
+ }
+ }
+ }
+ while (accelIterator != accelerators.begin());
+ }
+ return false;
+}
+
+bool
+Application::DirectMouseWheel_RegisterSkipClass(ATOM klass)
+{
+ size_t index;
+
+ if (klass < 0xC000)
+ return false;
+
+ index = directMouseWheelBlackList.size();
+ while(index--)
+ {
+ if (directMouseWheelBlackList[index] == klass)
+ return false;
+ }
+
+ directMouseWheelBlackList.push_back(klass);
+
+ return true;
+}
+
+bool
+Application::DirectMouseWheel_UnregisterSkipClass(ATOM klass)
+{
+ size_t index;
+
+ if (klass < 0xC000)
+ return false;
+
+ index = directMouseWheelBlackList.size();
+ while(index--)
+ {
+ if (directMouseWheelBlackList[index] == klass)
+ {
+ directMouseWheelBlackList.erase(directMouseWheelBlackList.begin() + index);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+Application::DirectMouseWheel_EnableConvertToMouseWheel(HWND hwnd, BOOL enable)
+{
+ return (0 != ::DirectMouseWheel_EnableConvertToMouseWheel(hwnd, enable));
+}
+
+void
+Application::DirectMouseWheel_InitBlackList()
+{
+ size_t index;
+ WNDCLASSW klassInfo;
+ ATOM klassAtom;
+
+ const static LPCWSTR defaultBlackListNames[] =
+ {
+ L"msctls_trackbar32",
+ L"msctls_updown32",
+ L"SysHeader32",
+ };
+
+ const static ATOM defaultBlackListAtoms[] =
+ {
+ 0xC017, // button
+ 0xC018, // edit
+ 0xC019, // static
+ 0xC01C, // combobox
+ };
+
+ for (index = 0; index < ARRAYSIZE(defaultBlackListAtoms); index++)
+ {
+ directMouseWheelBlackList.push_back(defaultBlackListAtoms[index]);
+ }
+
+ for (index = 0; index < ARRAYSIZE(defaultBlackListNames); index++)
+ {
+ klassAtom = (ATOM)GetClassInfoW(NULL, defaultBlackListNames[index], &klassInfo);
+ if (0 != klassAtom)
+ directMouseWheelBlackList.push_back(klassAtom);
+ }
+}
+
+bool
+Application::DirectMouseWheel_ProccessMessage(MSG *msg)
+{
+ HWND targetWindow;
+ ATOM targetAtom;
+ DWORD targetProcessId;
+ POINT mousePoint;
+ size_t index, listSize;
+
+ if (msg->message != WM_MOUSEWHEEL)
+ return false;
+
+ if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
+ {
+ if (FALSE == DirectMouseWheel_RegisterMessage())
+ return false;
+ }
+
+ POINTSTOPOINT(mousePoint, msg->lParam);
+ targetWindow = WindowFromPoint(mousePoint);
+
+ if (NULL == targetWindow || targetWindow == msg->hwnd)
+ return false;
+
+ GetWindowThreadProcessId(targetWindow, &targetProcessId);
+ if (targetProcessId != GetCurrentProcessId())
+ return false;
+
+ if (FALSE == IsWindowEnabled(targetWindow))
+ return false;
+
+ listSize = directMouseWheelBlackList.size();
+ index = 0;
+
+ while(index != listSize)
+ {
+ targetAtom = (ATOM)GetClassLongPtrW(targetWindow, GCW_ATOM);
+ for(index = 0; index < listSize; index++)
+ {
+ if (targetAtom == directMouseWheelBlackList[index])
+ {
+ targetWindow = GetAncestor(targetWindow, GA_PARENT);
+ if (NULL == targetWindow || targetWindow == msg->hwnd)
+ return false;
+ break;
+ }
+ }
+ }
+
+ if (FALSE != DirectMouseWheel_IsConvertToMouseWheelEnabled(targetWindow))
+ {
+ SendMessageW(targetWindow, WM_MOUSEWHEEL, msg->wParam, msg->lParam);
+ return true;
+ }
+ else if (0 != SendMessageW(targetWindow, WINAMP_WM_DIRECT_MOUSE_WHEEL, msg->wParam, msg->lParam))
+ return true;
+
+ return false;
+}
+
+HWND ActiveChildWindowFromPoint( HWND hwnd, POINTS cursor_s, const int *controls, size_t controlsCount )
+{
+ POINT pt;
+ RECT controlRect;
+ HWND controlWindow;
+
+ POINTSTOPOINT( pt, cursor_s );
+
+ while ( controlsCount-- )
+ {
+ controlWindow = GetDlgItem( hwnd, controls[ controlsCount ] );
+
+ if ( controlWindow != NULL && GetClientRect( controlWindow, &controlRect ) != FALSE )
+ {
+ MapWindowPoints( controlWindow, HWND_DESKTOP, (POINT *) &controlRect, 2 );
+
+ if ( PtInRect( &controlRect, pt ) != FALSE )
+ {
+ unsigned long windowStyle = (unsigned long) GetWindowLongPtrW( controlWindow, GWL_STYLE );
+
+ if ( ( ( WS_VISIBLE | WS_DISABLED ) & windowStyle ) == WS_VISIBLE )
+ return controlWindow;
+
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+BOOL DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam, const int controls[], int controlslen)
+{
+ if (FALSE != ::IsDirectMouseWheelMessage(uMsg))
+ {
+ HWND targetWindow = ::ActiveChildWindowFromPoint(hwnd, MAKEPOINTS(lParam), controls, controlslen);
+ if (NULL != targetWindow)
+ {
+ SendMessageW(targetWindow, WM_MOUSEWHEEL, wParam, lParam);
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (long)TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL Application::DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam, const int controls[], int controlslen)
+{
+ return ::DirectMouseWheel_ProcessDialogMessage(hwnd, uMsg, wParam, lParam, controls, controlslen);
+}
+
+void Application::ActiveDialog_Register(HWND hwnd)
+{
+ activeDialog = hwnd;
+}
+
+void Application::ActiveDialog_Unregister(HWND hwnd)
+{
+ if (hwnd == activeDialog)
+ activeDialog = NULL;
+}
+
+HWND Application::ActiveDialog_Get()
+{
+ return activeDialog;
+}
+
+/* Plugins can register a 'Message Processor' to tap into the main message loop
+ for some purposes (Dialog message handling, ActiveX/ATL/COM, wxWidgets)
+ this is the only way to make sure all messages are processed correctly
+ @see api_application::app_addMessageProcessor() and api_messageprocessor.h
+ */
+
+bool Application::ProcessMessageLight( MSG *msg )
+{
+ /* messageProcessors is the list of registered Message Processors */
+ for ( api_messageprocessor *processor : messageProcessors )
+ {
+ disableMessageHook = true;
+
+ if ( processor->ProcessMessage( msg ) ) // it'll return true if it wants to eat the message
+ {
+ disableMessageHook = false;
+
+ return true;
+ }
+ }
+
+ disableMessageHook = false;
+
+ if ( false != DirectMouseWheel_ProccessMessage( msg ) )
+ return true;
+
+ return false;
+}
+
+bool Application::ProcessMessage( MSG *msg )
+{
+ if ( ProcessMessageLight( msg ) != false )
+ return true;
+
+ if ( ( msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN ) && app_translateAccelerators( msg ) )
+ return true;
+
+
+ if ( activeDialog != NULL )
+ {
+ disableMessageHook = true;
+
+ if ( IsDialogMessageW( activeDialog, msg ) != FALSE )
+ {
+ disableMessageHook = false;
+
+ return true;
+ }
+ }
+
+ disableMessageHook = false;
+
+ return false;
+}
+
+intptr_t Application::app_messageLoopStep()
+{
+ MSG msg;
+
+ if (PeekMessageW(&msg, NULL, 0, 0, TRUE))
+ {
+ if (msg.message == WM_QUIT)
+ {
+ PostQuitMessage((int)msg.wParam);
+ return msg.wParam ; // abandoned due to WM_QUIT
+ }
+
+ if (!ProcessMessage(&msg) && !FilterMessage(&msg))
+ DispatchMessageW(&msg);
+
+ if (WM_NCDESTROY == msg.message)
+ DirectMouseWheel_EnableConvertToMouseWheel(msg.hwnd, FALSE);
+
+ return msg.wParam;
+ }
+
+ return 0;
+}
+
+LRESULT CALLBACK Application::MessageHookProc( INT code, WPARAM wParam, LPARAM lParam )
+{
+ if ( application == NULL || application->messageHook == NULL )
+ {
+ return FALSE;
+ }
+
+ if ( application->disableMessageHook == false )
+ {
+ switch ( code )
+ {
+ case MSGF_DIALOGBOX:
+ case MSGF_MESSAGEBOX:
+ if ( false != application->ProcessMessageLight( (MSG *) lParam ) )
+ return 1;
+ break;
+ }
+ }
+ else
+ application->disableMessageHook = false;
+
+ return CallNextHookEx( application->messageHook, code, wParam, lParam );
+}
+
+WPARAM Application::MessageLoop()
+{
+ if ( messageHook == NULL )
+ messageHook = SetWindowsHookEx( WH_MSGFILTER, MessageHookProc, NULL, GetCurrentThreadId() );
+
+ for ( ;;)
+ {
+ DWORD dwStatus = MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE );
+
+ if ( dwStatus == WAIT_OBJECT_0 )
+ {
+ MSG msg;
+ while ( PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ) )
+ {
+ if ( msg.message == WM_QUIT )
+ return msg.wParam;
+
+ if ( !ProcessMessage( &msg ) && !FilterMessage( &msg ) )
+ DispatchMessageW( &msg );
+ }
+ }
+ }
+}
+
+WPARAM WinampMessageLoop()
+{
+ return WASABI_API_APP->MessageLoop();
+}
+
+const wchar_t *Application::path_getWorkingPath()
+{
+ return config_cwd;
+}
+
+void Application::path_setWorkingPath(const wchar_t *newPath)
+{
+ StringCchCopyW(config_cwd, MAX_PATH, newPath);
+}
+
+/*
+int Application::GetMachineID(GUID *id)
+{
+ // TODO: stuff this in the registry
+ if (machineID == GUID_NULL)
+ {
+ if (!GetPrivateProfileStruct(app_name, "mid", (LPVOID)&machineID, sizeof(machineID), INI_FILE) || machineID == GUID_NULL)
+ {
+ UuidCreate(&machineID);
+ WritePrivateProfileStruct(app_name, "mid", (LPVOID)&machineID, sizeof(machineID), INI_FILE);
+ }
+ }
+
+ *id = machineID;
+ return API_APPLICATION_SUCCESS;
+}
+*/
+int Application::GetUserID(GUID *id)
+{
+ if (userID == GUID_NULL)
+ {
+ config_uid_ft = (char)GetPrivateProfileIntW(L"Winamp", L"uid_ft", 0, INI_FILE);
+
+ wchar_t uid_str[512] = {0};
+ if (!GetPrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA) || userID == GUID_NULL)
+ {
+ // attempt to restore the client uid after an uninstall, lost config file, etc
+ readwrite_client_uid(0, uid_str);
+ if (uid_str[0])
+ {
+ WritePrivateProfileStringW(AutoWide(app_name), L"uid", uid_str, INI_FILE);
+ }
+
+ if (!GetPrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA) || userID == GUID_NULL)
+ {
+ UuidCreate(&userID);
+ WritePrivateProfileStructA(app_name, "uid", (LPVOID)&userID, sizeof(userID), INI_FILEA);
+ GetPrivateProfileStringW(AutoWide(app_name), L"uid", L"", uid_str, ARRAYSIZE(uid_str), INI_FILE);
+ readwrite_client_uid(1, uid_str);
+ // if done then no need to re-do it at a later point
+ config_uid_ft = 1;
+ }
+ }
+
+ // and just to make sure, if this is like a new run then we'll need to force into the registry
+ if (!config_uid_ft)
+ {
+ config_uid_ft = 1;
+ GetPrivateProfileStringW(AutoWide(app_name), L"uid", L"", uid_str, ARRAYSIZE(uid_str), INI_FILE);
+ readwrite_client_uid(1, uid_str);
+ }
+ }
+
+ *id = userID;
+
+ return API_APPLICATION_SUCCESS;
+}
+
+int Application::GetSessionID(GUID *id)
+{
+ if (sessionID == GUID_NULL)
+ UuidCreate(&sessionID);
+
+ *id = sessionID;
+ return API_APPLICATION_SUCCESS;
+}
+
+size_t Application::AllocateThreadStorage()
+{
+ return (size_t)InterlockedIncrement(&threadStorageIndex);
+}
+
+void *Application::GetThreadStorage(size_t index)
+{
+ std::vector<void*> *ptrlist = (std::vector<void*> *)TlsGetValue(tlsIndex);
+ if (!ptrlist)
+ return 0;
+
+ if ((index+1) > ptrlist->size())
+ return 0;
+
+ return ptrlist->at(index);
+}
+
+void Application::SetThreadStorage(size_t index, void *value)
+{
+ std::vector<void*> *ptrlist = (std::vector<void*> *)TlsGetValue(tlsIndex);
+ if (!ptrlist)
+ {
+ ptrlist = new std::vector<void*>;
+ TlsSetValue(tlsIndex, ptrlist);
+ }
+ size_t ptrlist_size = ptrlist->size();
+ if ((index+1) > ptrlist_size)
+ {
+ ptrlist->reserve(index+1);
+ for (size_t i=ptrlist_size;i<=index;i++)
+ {
+ ptrlist->push_back(0);
+ }
+ }
+ ptrlist->at(index) = value;
+}
+
+const wchar_t *Application::getATFString()
+{
+ return config_titlefmt;
+}
+
+int Application::getScaleX(int x)
+{
+ return ScaleX(x);
+}
+
+int Application::getScaleY(int y)
+{
+ return ScaleY(y);
+}
+
+#define CBCLASS Application
+START_DISPATCH;
+CB(API_APPLICATION_MAIN_GETAPPNAME, main_getAppName)
+CB(API_APPLICATION_MAIN_GETVERSIONSTRING, main_getVersionString)
+CB(API_APPLICATION_MAIN_GETVERSIONSTRING2, main_getVersionNumString)
+CB(API_APPLICATION_MAIN_GETBUILDNUMBER, main_getBuildNumber)
+CB(API_APPLICATION_MAIN_GETGUID, main_getGUID)
+CB(API_APPLICATION_MAIN_GETMAINTHREADHANDLE, main_getMainThreadHandle)
+CB(API_APPLICATION_MAIN_GETHINSTANCE, main_gethInstance)
+CB(API_APPLICATION_MAIN_GETCOMMANDLINE, main_getCommandLine)
+VCB(API_APPLICATION_MAIN_SHUTDOWN, main_shutdown)
+VCB(API_APPLICATION_MAIN_CANCELSHUTDOWN, main_cancelShutdown)
+CB(API_APPLICATION_MAIN_ISSHUTTINGDOWN, main_isShuttingDown)
+CB(API_APPLICATION_PATH_GETAPPPATH, path_getAppPath)
+CB(API_APPLICATION_PATH_GETUSERSETTINGSPATH, path_getUserSettingsPath)
+CB(API_APPLICATION_PATH_GETSKINSETTINGSPATH, path_getSkinSettingsPath)
+CB(API_APPLICATION_APP_GETINITCOUNT, app_getInitCount)
+CB(API_APPLICATION_APP_MESSAGELOOPSTEP, app_messageLoopStep)
+VCB(API_APPLICATION_APP_ADDMESSAGEPROCESSOR, app_addMessageProcessor)
+VCB(API_APPLICATION_APP_REMOVEMESSAGEPROCESSOR, app_removeMessageProcessor)
+VCB(API_APPLICATION_APP_ADDMODELESSDIALOG, app_addModelessDialog)
+VCB(API_APPLICATION_APP_REMOVEMODELESSDIALOG, app_removeModelessDialog)
+VCB(API_APPLICATION_APP_ADDACCELERATORS, app_addAccelerators)
+VCB(API_APPLICATION_APP_REMOVEACCELERATORS, app_removeAccelerators)
+CB(API_APPLICATION_APP_TRANSLATEACCELERATORS, app_translateAccelerators);
+CB(API_APPLICATION_APP_GETACCELERATORS, app_getAccelerators);
+VCB(API_APPLICATION_APP_REGISTERGLOBALWINDOW, app_registerGlobalWindow);
+VCB(API_APPLICATION_APP_UNREGISTERGLOBALWINDOW, app_unregisterGlobalWindow);
+CB(API_APPLICATION_PATH_GETWORKINGPATH, path_getWorkingPath);
+VCB(API_APPLICATION_PATH_SETWORKINGPATH, path_setWorkingPath);
+CB(API_APPLICATION_DIRECTMOUSEWHEEL_REGISTERSKIPCLASS, DirectMouseWheel_RegisterSkipClass);
+CB(API_APPLICATION_DIRECTMOUSEWHEEL_UNREGISTERSKIPCLASS, DirectMouseWheel_UnregisterSkipClass);
+CB(API_APPLICATION_DIRECTMOUSEWHEEL_ENABLECONVERTTOMOUSEWHEEL, DirectMouseWheel_EnableConvertToMouseWheel);
+CB(API_APPLICATION_DIRECTMOUSEWHEEL_PROCESSDIALOGMESSAGE, DirectMouseWheel_ProcessDialogMessage);
+VCB(API_APPLICATION_ACTIVEDIALOG_REGISTER, ActiveDialog_Register);
+VCB(API_APPLICATION_ACTIVEDIALOG_UNREGISTER, ActiveDialog_Unregister);
+CB(API_APPLICATION_ACTIVEDIALOG_GET, ActiveDialog_Get);
+/*
+CB(API_APPLICATION_GETMACHINEID, GetMachineID);
+*/
+CB(API_APPLICATION_GETUSERID, GetUserID);
+CB(API_APPLICATION_GETSESSIONID, GetSessionID);
+CB(API_APPLICATION_ALLOCATETHREADSTORAGE, AllocateThreadStorage);
+CB(API_APPLICATION_GETTHREADSTORAGE, GetThreadStorage);
+VCB(API_APPLICATION_SETTHREADSTORAGE, SetThreadStorage);
+CB(API_APPLICATION_GETATFSTRING, getATFString);
+CB(API_APPLICATION_GETSCALEX, getScaleX);
+CB(API_APPLICATION_GETSCALEY, getScaleY);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file