aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/main.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/main.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/main.cpp')
-rw-r--r--Src/Winamp/main.cpp1892
1 files changed, 1892 insertions, 0 deletions
diff --git a/Src/Winamp/main.cpp b/Src/Winamp/main.cpp
new file mode 100644
index 00000000..b92dda2d
--- /dev/null
+++ b/Src/Winamp/main.cpp
@@ -0,0 +1,1892 @@
+/** (c) Nullsoft, Inc. C O N F I D E N T I A L
+ ** Filename: main.cpp
+ ** Project: Winamp
+ ** Description: Winamp initialization code
+ ** Author: Justin Frankel
+ ** Created: April 1997
+ **/
+
+#include "main.h"
+#include <windowsx.h>
+
+#include "../Agave/Language/lang.h"
+#include <stdarg.h>
+#include "vis.h"
+#include "fft.h"
+#include "gen.h"
+#include "../nu/ns_wc.h"
+#include "../nu/AutoWide.h"
+#include "../nu/AutoChar.h"
+#include "menuv5.h"
+#include "../Plugins/General/gen_ml/ml.h"
+#include "wa_dlg.h"
+#include "strutil.h"
+#include "./setup/setupfactory.h"
+#include "./commandLink.h"
+#include "AppRefCount.h"
+#include <unknwn.h>
+#include <shlwapi.h>
+#include <shobjidl.h>
+
+#include "WAT/WAT.h"
+
+#ifndef WM_DWMSENDICONICTHUMBNAIL
+#define WM_DWMSENDICONICTHUMBNAIL 0x0323
+#endif
+#include "Agave/Language/api_language.h"
+
+#ifndef WM_DWMSENDICONICLIVEPREVIEWBITMAP
+#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
+#endif
+
+#ifndef THBN_CLICKED
+#define THBN_CLICKED 0x1800
+#endif
+
+typedef HRESULT( WINAPI *CHANGEWINDOWMESSAGEFILTER )( UINT message, DWORD dwFlag );
+static HMODULE user32Lib = 0;
+static CHANGEWINDOWMESSAGEFILTER changeWMFilter;
+static BOOL changeWMLoadTried = FALSE;
+
+//#define BENSKI_TEST_WM_PRINTCLIENT
+static UINT WM_TASKBARCREATED;
+static UINT WM_TASKBARBUTTONCREATED;
+
+LARGE_INTEGER freq;
+UINT g_scrollMsg;
+UINT songChangeBroadcastMessage = 0;
+int g_noreg;
+int disable_skin_borders = 0;
+int no_notify_play = 0;
+int last_no_notify_play = 0;
+int main_delta_carryover = 0;
+int g_restartonquit = 0;
+char g_audiocdletter[ 4 ] = { 0 };
+int g_audiocdletters = 0;
+const char app_name[] = "Winamp", app_version[] = APP_VERSION, app_version_string[] = APP_VERSION_STRING; // application name and version strings
+int g_fullstop;
+char *app_date = __DATE__;
+int g_stopaftercur;
+int is_install;
+HWND hTooltipWindow, hEQTooltipWindow, hVideoTooltipWindow, hPLTooltipWindow;
+HWND hMainWindow = NULL; // main window
+HWND hEQWindow, hPLWindow, /*hMBWindow, */hVideoWindow, hExternalVisWindow = NULL;
+
+HWND g_dialog_box_parent = NULL; // used by IPC_SETDIALOGBOXPARENT (FG, 5/19/03)
+HINSTANCE language_pack_instance;
+HINSTANCE hMainInstance; // program instance
+HANDLE hMainThread; // main thread handle
+DWORD mainThreadId; // main thread ID
+HMENU main_menu = 0, top_menu = 0, g_submenus_bookmarks1 = 0,
+g_submenus_bookmarks2 = 0, g_submenus_skins1 = 0,
+g_submenus_skins2 = 0, g_submenus_vis = 0,
+g_submenus_options = 0, g_submenus_lang = 0,
+g_submenus_play = 0;
+
+int g_submenus_lang_id = 0;
+int g_video_numaudiotracks = 1;
+int g_video_curaudiotrack = 0;
+
+int bStartPlaying = 0;
+int paused = 0;
+int playing = 0;
+wchar_t caption[ CAPTION_SIZE ] = { 0 }; // current program caption
+wchar_t FileName[ FILENAME_SIZE ] = { 0 }; // current file name
+wchar_t FileTitle[ FILETITLE_SIZE ] = { 0 }; // current file title
+wchar_t FileTitleNum[ FILETITLE_SIZE ] = { 0 }; // current file title + track position
+int eggstat = 0; // used for easter eggs
+int g_srate, g_brate, g_nch, g_srate_exact;
+int last_brate = -1;
+int g_need_titleupd = 0;
+int g_need_infoupd = 0;
+int g_SkinTop, g_BookmarkTop, g_LangTop;
+int g_mm_optionsbase_adj = 0; //used by IPC_ADJUST_OPTIONSMENUPOS
+int g_mm_ffwindowsbase_adj = 0; //used by IPC_ADJUST_FFWINDOWSMENUPOS
+int g_mm_ffoptionsbase_adj = 0; //used by IPC_ADJUST_FFOPTIONSMENUPOS
+int g_has_video_plugin = 0;
+int g_no_video_loaded = 0; //filled in by in_init
+
+char playlist_custom_font[ 128 ] = { 0 };
+wchar_t playlist_custom_fontW[ 128 ] = { 0 };
+int config_custom_plfont = 1;
+int disable_skin_cursors = 0;
+int vis_fullscreen = 0;
+
+struct ITaskbarList3 *pTaskbar3 = NULL;
+
+static LRESULT Main_OnSysCommand( HWND hwnd, UINT cmd, int x, int y );
+
+HWND find_otherwinamp( wchar_t * );
+
+#undef HANDLE_WM_NCACTIVATE
+#define HANDLE_WM_NCACTIVATE(hwnd, wParam, lParam, fn) \
+ (LRESULT)(DWORD)(BOOL)(fn)((hwnd), (BOOL)(wParam), (HWND)(lParam), 0L)
+
+int stat_isit = 1; // used for faster version checkig
+wchar_t szAppName[ 64 ] = { 0 }; // window class name, generated on the fly.
+
+EXTERN_C BOOL eggTyping = FALSE;
+static char eggstr[] = "NULLSOFT";
+
+UINT USER_CONSENT_EVENT_ID = 123456;
+
+int g_exit_disabled = 0;
+int g_safeMode = 0;
+HANDLE g_hEventRunning;
+int bNoHwndOther = 0;
+
+static void CreateEQPresets()
+{
+ if ( !PathFileExistsW( EQDIR1 ) )
+ {
+ int x;
+ struct
+ {
+ char *s;
+ unsigned char tab[ 10 ];
+ }
+ eqsets[] =
+ {
+ {"Classical", {31, 31, 31, 31, 31, 31, 44, 44, 44, 48}},
+ {"Club", {31, 31, 26, 22, 22, 22, 26, 31, 31, 31}},
+ {"Dance", {16, 20, 28, 32, 32, 42, 44, 44, 32, 32}},
+ {"Flat", {31, 31, 31, 31, 31, 31, 31, 31, 31, 31}},
+ {"Laptop speakers/headphones", {24, 14, 23, 38, 36, 29, 24, 16, 11, 8}},
+ {"Large hall", {15, 15, 22, 22, 31, 40, 40, 40, 31, 31}},
+ {"Party", {20, 20, 31, 31, 31, 31, 31, 31, 20, 20}},
+ {"Pop", {35, 24, 20, 19, 23, 34, 36, 36, 35, 35}},
+ {"Reggae", {31, 31, 33, 42, 31, 21, 21, 31, 31, 31}},
+ {"Rock", {19, 24, 41, 45, 38, 25, 17, 14, 14, 14}},
+ {"Soft", {24, 29, 34, 36, 34, 25, 18, 16, 14, 12}},
+ {"Ska", {36, 40, 39, 33, 25, 22, 17, 16, 14, 16}},
+ {"Full Bass", {16, 16, 16, 22, 29, 39, 46, 49, 50, 50}},
+ {"Soft Rock", {25, 25, 28, 33, 39, 41, 38, 33, 27, 17}},
+ {"Full Treble", {48, 48, 48, 39, 27, 14, 6, 6, 6, 4}},
+ {"Full Bass & Treble", {20, 22, 31, 44, 40, 29, 18, 14, 12, 12}},
+ {"Live", {40, 31, 25, 23, 22, 22, 25, 27, 27, 28}},
+ {"Techno", {19, 22, 31, 41, 40, 31, 19, 16, 16, 17}},
+ };
+
+ for ( x = 0; x < sizeof( eqsets ) / sizeof( eqsets[ 0 ] ); x++ )
+ writeEQfile_init( EQDIR1, eqsets[ x ].s, eqsets[ x ].tab );
+ }
+}
+
+void BuildAppName()
+{
+ StringCchCopyW( szAppName, 64, L"Winamp v1.x" );
+ StringCchPrintfW( caption, CAPTION_SIZE, L"%S %S", app_name, app_version_string );
+}
+
+static void CALLBACK DisplayUserConsentMessageBox( HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD time )
+{
+ KillTimer( hMainWindow, USER_CONSENT_EVENT_ID );
+ if ( config_user_consent_join_channels != -1 )
+ {
+ return;
+ }
+
+ wchar_t titleStr[ 32 ] = { 0 };
+ int msgboxID = MessageBoxW(
+ NULL,
+ WASABI_API_LNGSTRINGW( IDS_RC_CHANNEL_MESSAGE ),
+ WASABI_API_LNGSTRINGW_BUF( IDS_RC_CHANNEL_TITLE, titleStr, 32 ),
+ MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON1
+ );
+
+ switch ( msgboxID )
+ {
+ case IDYES:
+ config_user_consent_join_channels = 1;
+ config_newverchk_rc = 1;
+ config_newverchk = 1;
+ break;
+ case IDNO:
+ config_user_consent_join_channels = 0;
+ config_newverchk_rc = 0;
+ config_newverchk = 1;
+ break;
+ }
+}
+
+// creates (but does not show) main window
+int CreateMainWindow()
+{
+ if ( !IsWindow( hMainWindow ) )
+ {
+ WNDCLASSW wcW = { 0 };
+
+ wcW.style = CS_DBLCLKS;
+ wcW.lpfnWndProc = Main_WndProc;
+ wcW.hInstance = hMainInstance;
+ wcW.hIcon = LoadIconW( hMainInstance, MAKEINTRESOURCE( ICON_XP ) );
+ wcW.hCursor = NULL;
+ wcW.lpszClassName = szAppName;
+
+ if ( !RegisterClassW( &wcW ) )
+ return 0;
+
+ if ( !CreateWindowExW( WS_EX_ACCEPTFILES, szAppName, L"Winamp", WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_BORDER | WS_CAPTION,
+ config_wx, config_wy, 0, 0, // WM_CREATE will size it
+ NULL, NULL, hMainInstance, NULL ) )
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+wchar_t *getGUIDstr( const GUID guid, wchar_t *target )
+{
+ StringCchPrintfW( target, 40, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0",
+ (int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
+ (int)guid.Data4[ 0 ], (int)guid.Data4[ 1 ], (int)guid.Data4[ 2 ], (int)guid.Data4[ 3 ],
+ (int)guid.Data4[ 4 ], (int)guid.Data4[ 5 ], (int)guid.Data4[ 6 ], (int)guid.Data4[ 7 ] );
+ return target;
+}
+
+BOOL parseMessageCommands( HWND hwnd_other, int bCommand, int bCmdParam )
+{
+ if ( LOWORD( bCommand ) ) // attempt to send the action to it
+ {
+ if ( HIWORD( bCommand ) == 1 )
+ {
+ SendMessageW( hwnd_other, WM_WA_IPC, bCmdParam, MAKELPARAM( LOWORD( bCommand ), 0 ) );
+ return TRUE;
+ }
+ else if ( HIWORD( bCommand ) == 2 )
+ {
+ // these need some additional processing which is easier to do once we're loaded
+ if ( LOWORD( bCommand ) == EQ_PANLEFT || LOWORD( bCommand ) == EQ_PANRIGHT ||
+ LOWORD( bCommand ) == IPC_SETPANNING )
+ {
+ int pan = IPC_GETPANNING( hwnd_other );
+ if ( LOWORD( bCommand ) == EQ_PANLEFT ) pan -= 12;
+ else if ( LOWORD( bCommand ) == EQ_PANRIGHT ) pan += 12;
+ else pan = bCmdParam;
+
+ if ( pan < -127 ) pan = -127;
+ if ( pan > 127 ) pan = 127;
+
+ SendMessageW( hwnd_other, WM_WA_IPC, pan, IPC_SETPANNING );
+ }
+ else if ( LOWORD( bCommand ) == IPC_ISPLAYING )
+ {
+ int command = SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_ISPLAYING );
+ switch ( command )
+ {
+ case 1: // playing so need to pause
+ command = WINAMP_BUTTON3;
+ break;
+ default: // stopped so start playing
+ command = WINAMP_BUTTON2;
+ break;
+ }
+ SendMessageW( hwnd_other, WM_COMMAND, command, 0 );
+ }
+ return TRUE;
+ }
+ else
+ {
+ SendMessageW( hwnd_other, WM_COMMAND, bCommand, 0 );
+
+ if ( LOWORD( bCommand ) == WINAMP_JUMPFILE )
+ {
+ // TODO need to make this locale independant...
+ HWND jumpWnd = FindWindowW( NULL, L"Jump to file" );
+ if ( IsWindow( jumpWnd ) )
+ {
+ SetForegroundWindow( jumpWnd );
+ }
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static int PassToOtherWinamp( wchar_t *lpszCmdParam, HWND hwnd_other, int bAdd, int bBookmark, int bHandle, int bCommand, int bCmdParam )
+{
+ // if we have command line params, pass to other winamp window
+ if ( lpszCmdParam && *lpszCmdParam )
+ {
+ int skinExit = 0;
+ int bC = 0;
+ HANDLE hSem = NULL;
+ HINSTANCE existingWLZ = 0, templng = 0;
+ DWORD_PTR vn = 0;
+
+ // check if we're using a language pack with the already open winamp process
+ // and if so then we're going to use the winamp.lng from it on the messagebox
+ // only if we had a success and the other winamp returned the correct value
+ // within the timeout period (can't be having it lock up so revert if needed)
+ if ( SendMessageTimeout( hwnd_other, WM_WA_IPC, 1, IPC_GETLANGUAGEPACKINSTANCE, SMTO_NORMAL, 5000, &vn ) && !vn )
+ {
+ DWORD processid = 0;
+ HANDLE hwaProcess = NULL;
+ SIZE_T bread = 0;
+ wchar_t lng_path_copy[ MAX_PATH ] = { 0 }, dirmask[ MAX_PATH ] = { 0 }, gs[ 40 ] = { 0 };
+ WIN32_FIND_DATAW d = { 0 };
+
+ GetWindowThreadProcessId( hwnd_other, &processid );
+ hwaProcess = OpenProcess( PROCESS_VM_READ, FALSE, processid );
+ ReadProcessMemory( hwaProcess, (wchar_t *)SendMessageW( hwnd_other, WM_WA_IPC, 3, IPC_GETLANGUAGEPACKINSTANCE ), lng_path_copy, MAX_PATH, &bread );
+ CloseHandle( hwaProcess );
+
+ getGUIDstr( WinampLangGUID, gs );
+ PathCombineW( dirmask, lng_path_copy, L"*.lng" );
+ HANDLE h = FindFirstFileW( dirmask, &d );
+ if ( h != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ PathCombineW( dirmask, lng_path_copy, d.cFileName );
+ templng = LoadLibraryExW( dirmask, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE );
+ if ( !templng ) templng = LoadLibraryW( dirmask );
+ if ( templng )
+ {
+ wchar_t s[ 39 ] = { 0 };
+ if ( LoadStringW( templng, LANG_DLL_GUID_STRING_ID, s, 39 ) )
+ {
+ if ( !_wcsnicmp( gs, s, 38 ) )
+ {
+ existingWLZ = Lang_FakeWinampLangHInst( templng );
+ }
+ else
+ FreeLibrary( templng );
+ }
+ else
+ FreeLibrary( templng );
+ }
+ } while ( FindNextFileW( h, &d ) );
+ FindClose( h );
+ }
+ }
+
+ lpszCmdParam = CheckSkin( lpszCmdParam, hwnd_other, &skinExit );
+ if ( skinExit )
+ {
+ // restore the language pack settings now that we've done the override and clean up as needed
+ if ( existingWLZ )
+ {
+ Lang_FakeWinampLangHInst( existingWLZ );
+ FreeLibrary( templng );
+ }
+ return TRUE;
+ }
+
+ skinExit = 0;
+ lpszCmdParam = CheckLang( lpszCmdParam, hwnd_other, &skinExit );
+ // restore the language pack settings now that we've done the override and clean up as needed
+ if ( existingWLZ )
+ {
+ Lang_FakeWinampLangHInst( existingWLZ );
+ FreeLibrary( templng );
+ }
+
+ if ( skinExit )
+ return TRUE;
+
+ hSem = CreateSemaphoreA( 0, 0, 65535, "WinampExplorerHack1" );
+
+ if ( hSem && GetLastError() != ERROR_ALREADY_EXISTS )
+ {
+ bC = 1;
+ if ( !bAdd && !bBookmark && !bHandle )
+ {
+ SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_DELETE_INT );
+ }
+ }
+ if ( hSem )
+ {
+ ReleaseSemaphore( hSem, 1, NULL );
+ if ( bBookmark )
+ {
+ static wchar_t tmp[ MAX_PATH ];
+ StringCchPrintfW( tmp, MAX_PATH, L"/BOOKMARK %s", lpszCmdParam );
+ lpszCmdParam = tmp;
+ }
+ else if ( bHandle )
+ {
+ static wchar_t tmp[ MAX_PATH ];
+ StringCchPrintfW( tmp, MAX_PATH, L"/HANDLE %s", lpszCmdParam );
+ lpszCmdParam = tmp;
+ }
+ parseCmdLine( lpszCmdParam, hwnd_other );
+
+ WaitForSingleObject( hSem, 5000 );
+ if ( bC )
+ {
+ int n = 500;
+ if ( !bAdd && !bBookmark && !bHandle ) SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_STARTPLAY_INT );
+ Sleep( 200 );
+ for ( ;;)
+ {
+ if ( WaitForSingleObject( hSem, 100 ) == WAIT_TIMEOUT )
+ {
+ if ( WaitForSingleObject( hSem, 900 ) == WAIT_TIMEOUT )
+ {
+ break;
+ }
+ else
+ {
+ ReleaseSemaphore( hSem, 1, NULL );
+ n--;
+ }
+ }
+ else
+ {
+ ReleaseSemaphore( hSem, 1, NULL );
+ Sleep( 100 );
+ n--;
+ }
+ }
+ }
+ CloseHandle( hSem );
+ }
+ }
+ else
+ {
+ if ( !parseMessageCommands( hwnd_other, bCommand, bCmdParam ) )
+ {
+ ShowWindow( hwnd_other, SW_RESTORE );
+ SetForegroundWindow( hwnd_other );
+ }
+ }
+ return TRUE;
+}
+
+DWORD CALLBACK MainThread( LPVOID param );
+extern wchar_t vidoutbuf_save[ 1024 ];
+static LPWSTR lpszCmdParam = 0;
+static int bAdd = 0, bBookmark = 0,
+bHandle = 0, bCommand = 0,
+bCmdParam = 0, bAllowCompat = 0;
+
+void ShowSafeModeMessage( int mode )
+{
+ if ( g_safeMode && ( g_safeMode != 3 ) )
+ {
+ wchar_t title[ 256 ] = { 0 }, message[ 512 ] = { 0 };
+ MSGBOXPARAMSW msgbx = { sizeof( MSGBOXPARAMSW ),0 };
+ if ( !mode )
+ {
+ msgbx.lpszText = getStringW( ( g_safeMode == 2 ? IDS_SAFE_MODE_ALL : IDS_SAFE_MODE_NORMAL ), message, 512 );
+ msgbx.lpszCaption = getStringW( IDS_START_SAFE_MODE, title, 256 );
+ }
+ else
+ {
+ msgbx.lpszText = getStringW( IDS_FAILED_SAFE_MODE_MSG, message, 512 );
+ msgbx.lpszCaption = getStringW( IDS_FAILED_SAFE_MODE, title, 256 );
+ }
+ msgbx.lpszIcon = MAKEINTRESOURCEW( 102 );
+ msgbx.hInstance = hMainInstance;
+ msgbx.dwStyle = MB_USERICON;
+ MessageBoxIndirectW( &msgbx );
+ }
+}
+
+#ifdef BETA
+time_t inline get_compile_time( char const *time )
+{
+ char s_month[ 5 ] = { 0 };
+ int day = 0, year = 0;
+ struct tm t = { 0 };
+ static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+ sscanf( time, "%s %d %d", s_month, &day, &year );
+
+ t.tm_mon = ( ( strstr( month_names, s_month ) - month_names ) / 3 );
+ t.tm_mday = day;
+ t.tm_year = year - 1900;
+ t.tm_isdst = -1;
+
+ return mktime( &t );
+}
+#endif
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR unused /*lpszCmdParam*/, int nCmdShow )
+{
+ INITCOMMONCONTROLSEX icex = { sizeof( icex ), ICC_WIN95_CLASSES | ICC_DATE_CLASSES };
+ InitCommonControlsEx( &icex );
+ QueryPerformanceFrequency( &freq );
+
+#if 0
+#ifdef BETA
+ // gives ~4 weeks from a build compile to when it'll show this (should be enough time)
+ time_t now = time( 0 ), compile = get_compile_time( app_date );
+ struct tm *tn = localtime( &now );
+ tn->tm_sec = tn->tm_min = tn->tm_hour = 0;
+ now = mktime( tn );
+
+ if ( ( now - compile ) >= 2678400 )
+ {
+ /* Skip the executable name in the commandline */
+ /* and check for /UNREG which we will allow so */
+ /* an expired beta can be uninstalled properly */
+ lpszCmdParam = GetCommandLineW();
+ lpszCmdParam = FindNextCommand( lpszCmdParam );
+ ParseParametersExpired( lpszCmdParam );
+
+ MSGBOXPARAMSW msgbx = {
+ sizeof( MSGBOXPARAMSW ),
+ 0,
+ GetModuleHandle( NULL ),
+ L"This beta version of Winamp is now over 4 weeks old.\n\n"
+ L"Please update to the latest Winamp version available.",
+ L"Winamp Beta Expired",
+ MB_USERICON,
+ MAKEINTRESOURCEW( 102 ),
+ 0, 0, 0
+ };
+ MessageBoxIndirectW( &msgbx );
+ ShellExecuteW( NULL, L"open", L"http://www.winamp.com/media-player", NULL, NULL, SW_SHOWNORMAL );
+ return 0;
+ }
+#endif
+#endif
+
+ DWORD threadId = 0, res = 0;
+ HANDLE mainThread = nullptr;
+ int cmdShow = nCmdShow;
+
+ /*void *refCounter = */InitAppRefCounterObject( GetCurrentThreadId() );
+ //SHSetInstanceExplorer((IUnknown *)refCounter);
+
+ SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
+
+ // don't load from working directory !!!!!
+ // requires XP SP3+
+ SetDllDirectoryW( L"" );
+
+ GetModuleFileNameW( NULL, SHAREDDIR, MAX_PATH );
+ PathRemoveFileSpecW( SHAREDDIR );
+ PathAppendW( SHAREDDIR, L"Shared" );
+ // load supporting dlls from the Winamp\Shared directory
+ SetDllDirectoryW( SHAREDDIR );
+
+ hMainInstance = hInstance;
+
+ /* Skip the executable name in the commandline */
+ lpszCmdParam = GetCommandLineW();
+ lpszCmdParam = FindNextCommand( lpszCmdParam );
+
+ BuildAppName();
+
+ init_config();
+ LoadPathsIni();
+ lpszCmdParam = ParseParameters( lpszCmdParam, &bAdd, &bBookmark, &bHandle, &cmdShow, &bCommand, &bCmdParam, &bAllowCompat );
+
+ setup_config();
+
+ // ensure we've got things set up as needed for safe mode being always on so we
+ // don't incorrectly prompt about entering it from using IPC_RESTARTSAFEWINAMP.
+ int mode = _r_i( "allowcompat", 0 );
+ if ( mode ) bAllowCompat = 1;
+
+ if ( !bAllowCompat && read_compatmode() )
+ {
+ MSGBOXPARAMSW msgbx = {
+ sizeof( MSGBOXPARAMSW ),
+ 0,
+ GetModuleHandle( NULL ),
+ L"Winamp appears to have been started with Windows program compatibility mode enabled.\n\n"
+ L"This is not a recommended way to run Winamp as it can often cause problems with how Winamp works e.g. causing it to randomly crash."
+ L"\n\n\nAre you sure you want to continue to run Winamp like this?\n\n\n"
+ L"If you choose 'No', you can disable this by right-clicking winamp.exe, choosing 'Properties' and selecting the 'Compatibility' tab, "
+ L"followed by unchecking 'Run this program in compatibility mode for:' and run Winamp again.",
+ L"Winamp",
+ MB_USERICON | MB_YESNO | MB_DEFBUTTON2,
+ MAKEINTRESOURCEW( 102 ),
+ 0, 0, 0
+ };
+ if ( MessageBoxIndirectW( &msgbx ) == IDNO )
+ {
+ return 0;
+ }
+ }
+
+
+ CoInitializeEx( 0, COINIT_MULTITHREADED );
+
+ // ensure we've got things set up as needed for safe mode being always on so we
+ // don't incorrectly prompt about entering it from using IPC_RESTARTSAFEWINAMP.
+ mode = _r_i( "safemode", 0 );
+ if ( mode ) g_safeMode = 3;
+
+ if ( 0 == ( 128 & is_install ) )
+ {
+ HWND hwnd_other = find_otherwinamp( lpszCmdParam );
+ if ( IsWindow( hwnd_other ) )
+ {
+ // unable to start safe mode so inform the user
+ ShowSafeModeMessage( 1 );
+ int x = PassToOtherWinamp( lpszCmdParam, hwnd_other, bAdd, bBookmark, bHandle, bCommand, bCmdParam );
+ CoUninitialize();
+ return x;
+ }
+ }
+
+ // unable to start safe mode so inform the user
+ ShowSafeModeMessage( 0 );
+
+ mainThread = CreateThread( 0, 0, MainThread, (LPVOID)cmdShow, 0, &threadId );
+
+ while ( !AppRefCount_CanQuit() )
+ {
+ DWORD dwStatus = MsgWaitForMultipleObjectsEx( 1, &mainThread, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE );
+ if ( dwStatus == WAIT_OBJECT_0 + 1 )
+ {
+ MSG msg;
+ while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+ {
+ if ( msg.message == WM_QUIT )
+ return msg.wParam;
+ DispatchMessage( &msg );
+ }
+ }
+ else if ( dwStatus == WAIT_OBJECT_0 )
+ {
+ GetExitCodeThread( mainThread, &res );
+ CloseHandle( mainThread );
+ AppRefCount_Release();
+ }
+ }
+ return 0;
+}
+
+static BOOL LoadWMFilter()
+{
+ if ( !changeWMLoadTried )
+ {
+ user32Lib = LoadLibraryA( "user32.dll" );
+ if ( user32Lib )
+ changeWMFilter = (CHANGEWINDOWMESSAGEFILTER)GetProcAddress( user32Lib, "ChangeWindowMessageFilter" );
+
+ changeWMLoadTried = TRUE;
+ }
+
+ return user32Lib && changeWMFilter;
+}
+
+VOID CALLBACK PrefsShowProc( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
+{
+ KillTimer( hwnd, idEvent );
+
+ if ( IsWindow( prefs_hwnd ) )
+ SetForegroundWindow( prefs_hwnd );
+}
+
+void load_gen_crasher()
+{
+ // this will load gen_crasher.dll as applicable (included in beta builds but not release mode by default)
+ // with extra checks to ensure it's 'valid' (as can be) so we could drop it into release builds as needed
+ wchar_t crasherDll[ MAX_PATH ] = { 0 };
+ PathCombineW( crasherDll, PLUGINDIR, L"gen_crasher.dll" );
+ HMODULE hm = LoadLibraryW( crasherDll );
+ if ( hm )
+ {
+ int( __cdecl * StartHandler )( wchar_t *iniPath ) = NULL;
+ *(FARPROC *)&StartHandler = GetProcAddress( hm, "StartHandler" );
+ if ( StartHandler )
+ {
+ wchar_t iniPath[ MAX_PATH ] = { 0 };
+ if ( SUCCEEDED( StringCchPrintfW( iniPath, MAX_PATH, L"%s\\Plugins", CONFIGDIR ) ) )
+ {
+ winampGeneralPurposePluginGetter pr = (winampGeneralPurposePluginGetter)GetProcAddress( hm, "winampGetGeneralPurposePlugin" );
+ if ( pr )
+ {
+ winampGeneralPurposePlugin *plugin = pr();
+ if ( plugin && plugin->version == GPPHDR_VER_U )
+ {
+ char desc[ 128 ] = { 0 };
+ lstrcpynA( desc, plugin->description, sizeof( desc ) );
+ if ( desc[ 0 ] && !memcmp( desc, "nullsoft(", 9 ) )
+ {
+ char *p = strrchr( desc, ')' );
+ if ( p )
+ {
+ *p = 0;
+ if ( !_wcsicmp( L"gen_crasher.dll", AutoWide( desc + 9 ) ) )
+ {
+ StartHandler( iniPath );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+ else
+ FreeLibrary( hm );
+ }
+}
+
+DWORD CALLBACK MainThread( LPVOID param )
+{
+ language_pack_instance = hMainInstance;
+
+ playlistStr[ 0 ] = 0;
+ playlistStr[ 18 ] = 0; // keep the last byte null terminated (and don't overwrite) so we can be smoewhat thread-safe (may have junk data, but it won't read outside the array)
+
+ vidoutbuf_save[ 0 ] = 0;
+ vidoutbuf_save[ 1023 ] = 0; // keep the last byte null terminated (and don't overwrite) so we can be smoewhat thread-safe (may have junk data, but it won't read outside the array)
+
+ mainThreadId = GetCurrentThreadId();
+ DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
+
+ InitializeCriticalSection( &embedcs );
+
+ CoInitialize( 0 );
+ Wasabi_Load();
+ plstring_init();
+ /*Browser_Create();*/
+
+
+ // check if it's gen_crasher.dll that's being removed and skip loading it so uninstall will work
+ bool skip_crasher = false;
+ wchar_t buf[ 1024 ] = { 0 };
+ _r_sW( "remove_genplug", buf, 1024 );
+ if ( buf[ 0 ] )
+ skip_crasher = !wcsicmp( PathFindFileNameW( buf ), L"gen_crasher.dll" );
+
+ if ( !skip_crasher )
+ load_gen_crasher();
+
+
+ if ( ( 128 & is_install ) || ( !g_noreg && GetPrivateProfileIntW( L"WinampReg", L"NeedReg", 1, INI_FILE ) ) )
+ {
+ is_install = 128; // nothing else
+ Setup_RegisterService();
+ }
+
+ draw_firstinit();
+
+ WM_TASKBARCREATED = RegisterWindowMessageA( "TaskbarCreated" );
+ g_scrollMsg = RegisterWindowMessageA( "MSWHEEL_ROLLMSG" );
+ WM_TASKBARBUTTONCREATED = RegisterWindowMessageW( L"TaskbarButtonCreated" );
+
+ if ( LoadWMFilter() )
+ {
+ changeWMFilter( WM_TASKBARBUTTONCREATED, 1/*MSGFLT_ADD*/ );
+ changeWMFilter( WM_DWMSENDICONICTHUMBNAIL, 1/*MSGFLT_ADD*/ );
+ changeWMFilter( WM_DWMSENDICONICLIVEPREVIEWBITMAP, 1/*MSGFLT_ADD*/ );
+ changeWMFilter( WM_COMMAND, 1/*MSGFLT_ADD*/ ); //for thumbnail toolbar buttons
+ }
+
+ CommandLink_RegisterClass( hMainInstance );
+
+ Skin_CleanupAfterCrash();
+ Lang_CleanupAfterCrash();
+
+ {
+ int langExit = 0;
+ lpszCmdParam = CheckLang( lpszCmdParam, 0, &langExit );
+ if ( langExit )
+ {
+ Lang_EndLangSupport();
+ Lang_CleanupZip();
+ return TRUE;
+ }
+ }
+
+ if ( !g_safeMode )
+ {
+ language_pack_instance = Lang_InitLangSupport( hMainInstance, WinampLangGUID );
+ Lang_FollowUserDecimalLocale();
+ }
+
+ if ( bBookmark )
+ {
+ w5s_init();
+
+ if ( !in_init() )
+ {
+ w5s_deinit();
+ Wasabi_Unload();
+ RemoveRegistrar();
+ CoUninitialize();
+ ExitProcess( 0 );
+ }
+
+ Bookmark_AddCommandline( lpszCmdParam );
+ in_deinit();
+ w5s_deinit();
+ Wasabi_Unload();
+ RemoveRegistrar();
+ CoUninitialize();
+ ExitProcess( 0 );
+ }
+
+ {
+ int skinExit = 0;
+ lpszCmdParam = CheckSkin( lpszCmdParam, 0, &skinExit );
+ if ( skinExit )
+ {
+ return TRUE;
+ }
+ }
+
+ {
+ // remove general purpose plug-in (if set)
+ wchar_t buf[ 1024 ] = { 0 };
+ _r_sW( "remove_genplug", buf, 1024 );
+ if ( buf[ 0 ] )
+ {
+ IFileTypeRegistrar *registrar = 0;
+ if ( GetRegistrar( &registrar, true ) == 0 && registrar )
+ {
+ registrar->DeleteItem( buf );
+ // if gen_crasher is requested to remove, also remove reporter.exe
+ if ( skip_crasher )
+ {
+ GetModuleFileNameW( NULL, buf, MAX_PATH );
+ PathRemoveFileSpecW( buf );
+ PathCombineW( buf, buf, L"reporter.exe" );
+ registrar->DeleteItem( buf );
+ }
+ registrar->Release();
+ }
+
+ _w_s( "remove_genplug", 0 );
+ }
+ }
+
+ fft_init();
+ SpectralAnalyzer_Create();
+ JSAPI1_Initialize();
+ stats_init();
+
+ w5s_init();
+
+
+ if ( !in_init() )
+ {
+ w5s_deinit();
+ Wasabi_Unload();
+ RemoveRegistrar();
+ CoUninitialize();
+ ExitProcess( 0 );
+ }
+
+ out_init();
+ vis_init();
+
+ if ( lpszCmdParam && *lpszCmdParam && !bAdd && !bHandle )
+ config_read( 1 );
+ else
+ config_read( 0 );
+
+ CreateEQPresets();
+
+ if ( is_install )
+ DoInstall( is_install );
+
+ reg_associated_filetypes( 0 );
+
+ if ( config_splash ) splashDlg( SPLASH_DELAY ); // display splash screen if desired
+
+ PlayList_getcurrent( FileName, FileTitle, FileTitleNum ); // update filename and filetitle if a list was loaded
+
+ songChangeBroadcastMessage = RegisterWindowMessageW( L"WinampSongChange" );
+
+ if ( !InitApplication( hMainInstance ) )
+ {
+ LPMessageBox( NULL, IDS_ERRORINIT, IDS_ERROR, MB_OK );
+ return FALSE;
+ }
+
+ if ( !InitInstance( hMainInstance, (int)param ) )
+ {
+ LPMessageBox( NULL, IDS_ERRORINIT, IDS_ERROR, MB_OK );
+ return FALSE;
+ }
+
+ if ( !bHandle )
+ {
+ if ( *lpszCmdParam ) // if command line parameters, parse them
+ {
+ parseCmdLine( lpszCmdParam, 0 );
+ plEditRefresh();
+ {
+ if ( config_shuffle )
+ PlayList_randpos( -BIGINT );
+
+ if ( !bAdd )
+ bStartPlaying = 1;
+ }
+ }
+ else // otherwise, we're using our loaded playlist
+ {
+ if ( config_shuffle ) PlayList_randpos( -BIGINT );
+ PlayList_getcurrent( FileName, FileTitle, FileTitleNum );
+ }
+ }
+
+ //SetCurrentDirectoryW(config_cwd);
+
+ plEditSelect( PlayList_getPosition() );
+
+ Ole_initDragDrop();
+
+ if ( !( GetAsyncKeyState( VK_RCONTROL ) & 0x8000 ) || !( GetAsyncKeyState( VK_LCONTROL ) & 0x8000 ) )
+ {
+ load_genplugins(); // load general purpose plugins
+
+ if ( !Skin_Check_Modern_Support() )
+ {
+ wchar_t msg[ 512 ] = { 0 };
+ StringCchPrintfW( msg, 512, getStringW( IDS_NO_MODERN_SKIN_SUPPORT, NULL, 0 ), config_skin );
+ MessageBoxW( NULL, msg, getStringW( IDS_SKIN_LOAD_ERROR, NULL, 0 ), MB_ICONWARNING | MB_OK | MB_TOPMOST );
+ }
+ }
+
+ //disable video menu if no video plugins are present or configured as disabled
+ if ( !g_has_video_plugin )
+ {
+ RemoveMenu( main_menu, WINAMP_OPTIONS_VIDEO, MF_BYCOMMAND );
+ RemoveMenu( GetSubMenu( v5_top_menu, 3 ), WINAMP_OPTIONS_VIDEO, MF_BYCOMMAND );
+ g_mm_optionsbase_adj -= 1;
+ }
+
+ set_aot( 0 ); // in case our gen plugins did anything fun
+ set_priority();
+
+ {
+ int v = _r_i( "show_prefs", 0 );
+ if ( v != 0 )
+ {
+ if ( v > 0 ) prefs_last_page = v;
+ _w_i( "show_prefs", 0 );
+ PostMessageW( hMainWindow, WM_COMMAND, WINAMP_OPTIONS_PREFS, 0 );
+ SetTimer( hMainWindow, 969, 1, PrefsShowProc );
+ }
+ }
+
+ if ( bStartPlaying )
+ {
+ PlayList_getcurrent( FileName, FileTitle, FileTitleNum );
+ SendMessageW( hMainWindow, WM_COMMAND, WINAMP_BUTTON2, 0 );
+ //SendMessageW(hMainWindow,WM_WA_IPC,0,IPC_STARTPLAY);
+ draw_paint( NULL );
+ }
+
+ WADlg_init( hMainWindow );
+
+ SetTimer( hMainWindow, USER_CONSENT_EVENT_ID, 5000, DisplayUserConsentMessageBox );
+
+#ifdef BENSKI_TEST_WM_PRINTCLIENT
+ SetTimer( hMainWindow, 9999, 10000, 0 );
+#endif
+
+ if ( bHandle && *lpszCmdParam )
+ PostMessageW( hMainWindow, WM_WA_IPC, (WPARAM)lpszCmdParam, IPC_HANDLE_URI );
+
+ parseMessageCommands( hMainWindow, bCommand, bCmdParam );
+
+ WPARAM exitParam = WinampMessageLoop();
+ JSAPI1_Uninitialize();
+
+ unload_genplugins();
+ w5s_deinit();
+
+ stats_save();
+ SpectralAnalyzer_Destroy();
+
+ /*Browser_Destroy();*/
+ //RaiseException(0x0000DEAD,0,0,0);
+
+ Ole_uninitDragDrop();
+
+ if ( g_restartonquit )
+ {
+ char buf[ MAX_PATH ] = "\"";
+ STARTUPINFO si = { sizeof( si ), };
+ PROCESS_INFORMATION pi;
+ GetModuleFileNameA( NULL, buf + 1, sizeof( buf ) - 1 );
+ StringCchCatA( buf, MAX_PATH, "\"" );
+
+ if ( g_restartonquit == 2 )
+ StringCchCatA( buf, MAX_PATH, " /SAFE=1" );
+
+ CreateProcessA( NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, (LPSTARTUPINFOA)&si, &pi );
+ }
+
+ RemoveRegistrar();
+ Wasabi_Unload();
+ CoUninitialize();
+ return exitParam;
+} // WinMain
+
+void MoveOffscreen( HWND hwnd )
+{
+ RECT r;
+ GetWindowRect( hwnd, &r );
+ SetWindowPos( hwnd, 0, r.left, OFFSCREEN_Y_POS, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
+}
+
+int g_showcode, deferring_show = 0;
+
+#include "../Plugins/General/gen_ml/ml_ipc.h"
+
+extern librarySendToMenuStruct mainSendTo = { 0 };
+
+// used to delay / filter out quick IPC_SETDIALOGBOXPARENT messages
+// to try to prevent the aero-peek buttons failing / part loading
+#define AEROPEEKLOAD 0xC0DE+5
+VOID CALLBACK TaskButtonCreated( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
+{
+ KillTimer( hwnd, idEvent );
+ OnTaskbarButtonCreated( TRUE );
+}
+
+void UpdateAudioCDMenus( HMENU hmenu )
+{
+ wchar_t buf[ 32 ] = { 0 };
+ if ( IsMenu( hmenu ) && in_get_extended_fileinfoW( L"cda://", L"ext_cdda", buf, ARRAYSIZE( buf ) ) && buf[ 0 ] == L'1' )
+ {
+ for ( int i = 0; i < 5; i++ )
+ {
+ DeleteMenu( hmenu, ID_MAIN_PLAY_AUDIOCD + i, MF_BYCOMMAND );
+ }
+
+ MENUITEMINFOW i = { sizeof( i ), MIIM_TYPE | MIIM_DATA | MIIM_ID, MFT_STRING, };
+ i.wID = ID_MAIN_PLAY_AUDIOCD;
+
+ DWORD drives = GetLogicalDrives();
+ g_audiocdletters = 0;
+
+ int need_sep = 1;
+ for ( int drivemask = 0; drivemask < 32; drivemask++ )
+ {
+ if ( drives & ( 1 << drivemask ) )
+ {
+ int old_error_mode = SetErrorMode( SEM_FAILCRITICALERRORS );
+ wchar_t str[ 64 ] = { 0 }, tmp[ 64 ] = { 0 }, vol_buf[ 40 ] = { 0 }, empty[ 64 ] = { 0 };
+ DWORD system_flags = 0, max_file_len = 0;
+ char c = ( 'A' + drivemask );
+ StringCchPrintfW( str, 64, L"%c:\\", c );
+
+ if ( GetDriveTypeW( str ) == DRIVE_CDROM )
+ {
+ if ( need_sep )
+ {
+ MENUITEMINFO i2 = { sizeof( i2 ), MIIM_TYPE | MIIM_ID, MFT_SEPARATOR, };
+ i2.wID = ID_MAIN_PLAY_AUDIOCD_SEP;
+ InsertMenuItem( hmenu, 4, TRUE, &i2 );
+ need_sep = 0;
+ }
+
+ GetVolumeInformationW( str, vol_buf, ARRAYSIZE( vol_buf ), 0, &max_file_len, &system_flags, 0, 0 );
+ SetErrorMode( old_error_mode );
+
+ StringCchPrintfW( str, 256, getStringW( IDS_AUDIO_CD, tmp, 64 ), c, ( vol_buf[ 0 ] ? vol_buf : getStringW( IDS_EMPTY, empty, 64 ) ) );
+
+ g_audiocdletter[ g_audiocdletters ] = c;
+ i.dwTypeData = str;
+ i.cch = (UINT)wcslen( str );
+ InsertMenuItemW( hmenu, 4 + g_audiocdletters, TRUE, &i );
+ i.wID++;
+
+ g_audiocdletters++;
+ if ( g_audiocdletters == 4 )
+ break;
+ }
+ }
+ }
+ }
+}
+
+// Main Winamp window procedure
+// we use message crackers when available, write our own for the ones that aren't
+LRESULT CALLBACK Main_WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( uMsg == g_scrollMsg )
+ {
+ wParam <<= 16;
+ uMsg = WM_MOUSEWHEEL;
+ }
+
+ if ( uMsg == WM_TASKBARCREATED )
+ {
+ if ( systray_intray )
+ {
+ systray_restore();
+ systray_minimize( caption );
+ }
+ return 0;
+ }
+
+ if ( uMsg == WM_TASKBARBUTTONCREATED )
+ {
+ OnTaskbarButtonCreated( TRUE );
+ KillTimer( hMainWindow, AEROPEEKLOAD );
+ SetTimer( hMainWindow, AEROPEEKLOAD, 250, TaskButtonCreated );
+ return 0;
+ }
+
+ if ( IsDirectMouseWheelMessage( uMsg ) != FALSE )
+ {
+ SendMessageW( hwnd, WM_MOUSEWHEEL, wParam, lParam );
+ return TRUE;
+ }
+
+ switch ( uMsg )
+ {
+ case WM_INITMENUPOPUP:
+ {
+ HMENU hMenu = (HMENU)wParam;
+ if ( wParam && hMenu == mainSendTo.build_hMenu && mainSendTo.mode == 1 )
+ {
+ int IPC_LIBRARY_SENDTOMENU = wa_register_ipc( ( WPARAM ) & "LibrarySendToMenu" );
+ if ( IPC_LIBRARY_SENDTOMENU > 65536 && SendMessageW( hMainWindow, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU ) == 0xffffffff )
+ mainSendTo.mode = 2;
+ }
+
+ if ( config_usecursors && !disable_skin_cursors )
+ {
+ if ( Skin_Cursors[ 2 ] )
+ SetCursor( Skin_Cursors[ 2 ] );
+ else
+ SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
+ }
+ else
+ SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
+
+ if ( hMenu == main_menu )
+ {
+ MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
+ l_menu_info.fMask = MIIM_TYPE;
+ l_menu_info.fType = MFT_STRING;
+ l_menu_info.dwTypeData = getStringW( IDS_WINAMP_MENUITEM, NULL, 0 );
+ l_menu_info.cch = (UINT)wcslen( l_menu_info.dwTypeData );
+ SetMenuItemInfoW( main_menu, 0, TRUE, &l_menu_info );
+ EnableMenuItem( main_menu, WINAMP_FILE_QUIT, MF_BYCOMMAND | ( g_exit_disabled ? MF_GRAYED : MF_ENABLED ) );
+ }
+ else if ( hMenu == g_submenus_play )
+ {
+ UpdateAudioCDMenus( g_submenus_play );
+ }
+ else if ( hMenu == g_submenus_bookmarks1 || hMenu == g_submenus_bookmarks2 )
+ {
+ MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
+ FILE *fp = 0;
+ int a = 34768;
+ int offs = 3;
+ int count = GetMenuItemCount( hMenu ) + 1;
+ if ( hMenu != g_submenus_bookmarks1 )
+ offs = 0;
+
+ l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID;
+ l_menu_info.fType = MFT_STRING;
+ l_menu_info.wID = 34768;
+
+ // this will remove the "(no bookmarks)" item from Main menu->Play->Bookmsrk
+ // if it still exists -> removed as of 5.55 since we handle the menu better.
+ if ( !offs ) RemoveMenu( hMenu, ID_MAIN_PLAY_BOOKMARK_NONE, MF_BYCOMMAND );
+
+ // remove all of the items we might have added - do by command for certainty
+ while ( count )
+ {
+ if ( !RemoveMenu( hMenu, a++, MF_BYCOMMAND ) ) break;
+ count--;
+ }
+
+ fp = _wfopen( BOOKMARKFILE8, L"rt" );
+ if ( fp )
+ {
+ while ( 1 )
+ {
+ char ft[ 4096 ] = { 0 }, fn[ MAX_PATH ] = { 0 };
+ fgets( fn, MAX_PATH, fp );
+ if ( feof( fp ) ) break;
+ fgets( ft, 4096, fp );
+ if ( feof( fp ) ) break;
+ if ( ft[ 0 ] && fn[ 0 ] )
+ {
+ if ( fn[ lstrlenA( fn ) - 1 ] == '\n' ) fn[ lstrlenA( fn ) - 1 ] = 0;
+ if ( ft[ lstrlenA( ft ) - 1 ] == '\n' ) ft[ lstrlenA( ft ) - 1 ] = 0;
+ if ( ft[ 0 ] && fn[ 0 ] )
+ {
+ l_menu_info.dwTypeData = AutoWideDup( ft, CP_UTF8 );
+ l_menu_info.cch = lstrlenW( l_menu_info.dwTypeData );
+ RemoveMenu( hMenu, l_menu_info.wID, MF_BYCOMMAND );
+ InsertMenuItemW( hMenu, l_menu_info.wID + offs - 34768, TRUE, &l_menu_info );
+ l_menu_info.wID++;
+ }
+ }
+ }
+ fclose( fp );
+ }
+
+ g_BookmarkTop = l_menu_info.wID;
+
+ // put in a place holder item if there were no read bookmarks
+ if ( g_BookmarkTop == 34768 )
+ {
+ l_menu_info.dwTypeData = getStringW( IDS_NO_BOOKMARKS, NULL, 0 );
+ l_menu_info.cch = lstrlenW( l_menu_info.dwTypeData );
+ InsertMenuItemW( hMenu, l_menu_info.wID + offs - 34768, TRUE, &l_menu_info );
+ EnableMenuItem( hMenu, l_menu_info.wID, MF_BYCOMMAND | MF_GRAYED );
+ }
+ }
+ else if ( hMenu == g_submenus_skins1 || hMenu == g_submenus_skins2 )
+ {
+ MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
+ HANDLE h;
+ WIN32_FIND_DATAW d = { 0 };
+ wchar_t dirmask[ MAX_PATH ] = { 0 };
+
+ l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE;
+ l_menu_info.fType = MFT_STRING;
+ l_menu_info.wID = 32768;
+ PathCombineW( dirmask, SKINDIR, L"*" );
+
+ if ( !config_skin[ 0 ] )
+ CheckMenuItem( hMenu, 32767, MF_CHECKED );
+ else
+ CheckMenuItem( hMenu, 32767, MF_UNCHECKED );
+
+ h = FindFirstFileW( dirmask, &d );
+ if ( h != INVALID_HANDLE_VALUE )
+ {
+ int a = 0, mod_got = 0, bento_got = 0, checked = 0;
+ do
+ {
+ if ( !wcscmp( d.cFileName, L"." ) || !wcscmp( d.cFileName, L".." ) ) continue;
+ if ( ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ||
+ !_wcsicmp( extensionW( d.cFileName ), L"zip" ) ||
+ !_wcsicmp( extensionW( d.cFileName ), L"wal" ) ||
+ !_wcsicmp( extensionW( d.cFileName ), L"wsz" ) )
+ {
+ if ( !_wcsicmp( config_skin, d.cFileName ) )
+ {
+ l_menu_info.fState = MFS_CHECKED | MFS_ENABLED;
+ checked = 1;
+ }
+ else
+ {
+ l_menu_info.fState = MFS_UNCHECKED | MFS_ENABLED;
+ }
+
+ if ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ l_menu_info.dwItemData = 0;
+ else
+ {
+ if ( !_wcsicmp( extensionW( d.cFileName ), L"zip" ) )
+ l_menu_info.dwItemData = 1;
+ else if ( !_wcsicmp( extensionW( d.cFileName ), L"wal" ) )
+ l_menu_info.dwItemData = 4;
+ else
+ l_menu_info.dwItemData = 2;
+ extensionW( d.cFileName )[ -1 ] = 0;
+ }
+
+ l_menu_info.dwTypeData = d.cFileName;
+ l_menu_info.cch = (UINT)wcslen( d.cFileName );
+ if ( !a )
+ if ( !RemoveMenu( hMenu, l_menu_info.wID + 4 - 32768, MF_BYPOSITION ) )
+ a = 1;
+
+ if ( !l_menu_info.dwItemData && !_wcsicmp( d.cFileName, MODERN_SKIN_NAME ) )
+ {
+ mod_got = 1;
+ InsertMenuItemW( hMenu, 4, TRUE, &l_menu_info );
+ }
+ else if ( !_wcsicmp( d.cFileName, BENTO_SKIN_NAME ) )
+ {
+ // place below classic + modern (if it exists)
+ bento_got = 1;
+ InsertMenuItemW( hMenu, 4 + mod_got, TRUE, &l_menu_info );
+ }
+ else if ( !_wcsicmp( d.cFileName, BIG_BENTO_SKIN_NAME ) )
+ {
+ // place below classic + modern + normal bento (if it exists)
+ InsertMenuItemW( hMenu, 4 + mod_got + bento_got, TRUE, &l_menu_info );
+ }
+ else
+ InsertMenuItemW( hMenu, l_menu_info.wID + 4 - 32768, TRUE, &l_menu_info );
+
+ l_menu_info.wID++;
+ }
+ } while ( l_menu_info.wID < 34700 && FindNextFileW( h, &d ) );
+ FindClose( h );
+ g_SkinTop = l_menu_info.wID;
+ while ( !a ) if ( !RemoveMenu( hMenu, l_menu_info.wID++ + 4 - 32768, MF_BYPOSITION ) ) a = 1;
+ if ( !checked ) CheckMenuItem( hMenu, 32767, MF_CHECKED );
+ }
+ }
+ else if ( ( hMenu == g_submenus_lang ) && config_wlz_menu )
+ {
+ MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
+ HANDLE h;
+ WIN32_FIND_DATAW d = { 0 };
+ wchar_t dirmask[ MAX_PATH ] = { 0 };
+
+ l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE;
+ l_menu_info.fType = MFT_STRING;
+ l_menu_info.wID = 34700;
+ PathCombineW( dirmask, LANGDIR, L"*" );
+
+ l_menu_info.dwTypeData = L"English (US)";
+ l_menu_info.cch = (UINT)wcslen( l_menu_info.dwTypeData );
+ InsertMenuItemW( hMenu, l_menu_info.wID - 34700, TRUE, &l_menu_info );
+ l_menu_info.wID++;
+
+ CheckMenuItem( hMenu, 34700, ( !config_langpack[ 0 ] ? MF_CHECKED : MF_UNCHECKED ) );
+
+ h = FindFirstFileW( dirmask, &d );
+ if ( h != INVALID_HANDLE_VALUE )
+ {
+ int a = 0, checked = 0;
+ do
+ {
+ if ( !wcscmp( d.cFileName, L"." ) || !wcscmp( d.cFileName, L".." ) ) continue;
+
+ if ( ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ||
+ !_wcsicmp( extensionW( d.cFileName ), L"zip" ) ||
+ !_wcsicmp( extensionW( d.cFileName ), L"wlz" ) )
+ {
+
+ if ( !_wcsicmp( config_langpack, d.cFileName ) )
+ {
+ l_menu_info.fState = MFS_CHECKED | MFS_ENABLED;
+ checked = 1;
+ }
+ else
+ {
+ l_menu_info.fState = MFS_UNCHECKED | MFS_ENABLED;
+ }
+
+ if ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ wchar_t check[ MAX_PATH ] = { 0 };
+ PathCombineW( check, LANGDIR, d.cFileName );
+ PathCombineW( check, check, L"winamp.lng" );
+
+ if ( !PathFileExistsW( check ) )
+ continue;
+
+ l_menu_info.dwItemData = 0;
+ }
+ else
+ {
+ if ( !_wcsicmp( extensionW( d.cFileName ), L"zip" ) )
+ l_menu_info.dwItemData = 1;
+ else
+ l_menu_info.dwItemData = 2;
+
+ extensionW( d.cFileName )[ -1 ] = 0;
+ }
+
+ l_menu_info.dwTypeData = d.cFileName;
+ l_menu_info.cch = (UINT)wcslen( d.cFileName );
+
+ if ( !a )
+ if ( !RemoveMenu( hMenu, l_menu_info.wID - 34700, MF_BYPOSITION ) )
+ a = 1;
+
+ InsertMenuItemW( hMenu, l_menu_info.wID - 34700, TRUE, &l_menu_info );
+ l_menu_info.wID++;
+ }
+ } while ( l_menu_info.wID < 34800 && FindNextFileW( h, &d ) );
+
+ FindClose( h );
+ g_LangTop = l_menu_info.wID;
+ while ( !a )
+ if ( !RemoveMenu( hMenu, l_menu_info.wID++ - 34700, MF_BYPOSITION ) )
+ a = 1;
+
+ if ( !checked )
+ CheckMenuItem( hMenu, 34700, MF_CHECKED );
+ }
+ }
+ break;
+ }
+ case WM_DISPLAYCHANGE:
+ Main_OnDisplayChange( hwnd );
+ break;
+ case WM_WA_SYSTRAY:
+ return ( Main_OnWASystray( hwnd, (int)LOWORD( lParam ) ) ? 0 : -1L );
+ case WM_WA_MPEG_EOF:
+ return ( Main_OnWAMPEGEOF( hwnd ) ? 0 : -1L ); // sent by decode thread
+ case WM_WA_IPC:
+ return ( Main_OnIPC( hwnd, lParam, (int)(DWORD)wParam ) );
+
+ HANDLE_MSG( hwnd, WM_COMMAND, Main_OnCommand );
+ HANDLE_MSG( hwnd, WM_SYSCOMMAND, Main_OnSysCommand );
+ HANDLE_MSG( hwnd, WM_CREATE, Main_OnCreate );
+ HANDLE_MSG( hwnd, WM_QUERYNEWPALETTE, Main_OnQueryNewPalette );
+ HANDLE_MSG( hwnd, WM_PALETTECHANGED, Main_OnPaletteChanged );
+ HANDLE_MSG( hwnd, WM_SIZE, Main_OnSize );
+ HANDLE_MSG( hwnd, WM_DROPFILES, Main_OnDropFiles );
+ HANDLE_MSG( hwnd, WM_TIMER, Main_OnTimer );
+ HANDLE_MSG( hwnd, WM_PAINT, draw_paint );
+ case WM_PRINTCLIENT:
+ draw_printclient( (HDC)wParam, lParam );
+ return 0;
+
+ HANDLE_MSG( hwnd, WM_RBUTTONUP, Main_OnRButtonUp );
+ HANDLE_MSG( hwnd, WM_LBUTTONDBLCLK, Main_OnLButtonDblClk );
+ HANDLE_MSG( hwnd, WM_LBUTTONUP, Main_OnLButtonUp );
+ HANDLE_MSG( hwnd, WM_LBUTTONDOWN, Main_OnLButtonDown );
+ HANDLE_MSG( hwnd, WM_MOUSEMOVE, Main_OnMouseMove );
+ case WM_CONTEXTMENU:
+ SendMessageW( hwnd, WM_COMMAND, WINAMP_MAINMENU, 0 );
+ return 0;
+ case WM_CAPTURECHANGED:
+ return Main_OnCaptureChanged( (HWND)lParam );
+
+ HANDLE_MSG( hwnd, WM_DESTROY, Main_OnDestroy );
+ HANDLE_MSG( hwnd, WM_CLOSE, Main_OnClose );
+ case WM_NCACTIVATE:
+ {
+ LRESULT result = (LRESULT)(DWORD)(BOOL)(Main_OnNCActivate)( ( hwnd ), (BOOL)( wParam ), (HWND)( lParam ), 0L );
+ if ( IsIconic( hwnd ) )
+ break;
+ else
+ return result;
+ }
+ case WM_NCHITTEST:
+ if ( IsIconic( hwnd ) )
+ break;
+ return (LRESULT)(DWORD)(UINT)(Main_OnNCHitTest)( ( hwnd ), (int)(short)LOWORD( lParam ), (int)(short)HIWORD( lParam ) );
+ case WM_NCCALCSIZE:
+ if ( IsIconic( hwnd ) )
+ break;
+ return (LRESULT)(DWORD)(UINT)Main_OnNCCalcSize( hwnd, (BOOL)wParam, (NCCALCSIZE_PARAMS *)lParam );
+
+ HANDLE_MSG( hwnd, WM_ENDSESSION, Main_OnEndSession );
+ case WM_QUERYENDSESSION:
+ return !!SendMessageW( hwnd, WM_WA_IPC, 0, IPC_HOOK_OKTOQUIT );
+ case WM_KEYDOWN:
+ {
+ static int pos;
+ TCHAR buf[ 2 ] = { (TCHAR)wParam, 0 };
+ CharUpperBuff( buf, 1 );
+
+ if ( buf[ 0 ] == eggstr[ pos ] )
+ {
+ eggTyping = TRUE;
+ if ( !eggstr[ ++pos ] )
+ {
+ eggTyping = FALSE;
+ eggstat = !eggstat;
+ pos = 0;
+ draw_tbar( 1, config_windowshade, eggstat );
+ }
+ }
+ else
+ pos = 0;
+
+ break;
+ }
+ case WM_NCPAINT:
+ return 0;
+ case WM_COPYDATA:
+ return Main_OnCopyData( (HWND)wParam, (COPYDATASTRUCT *)lParam );
+ case WM_GETTEXT:
+ return Main_OnGetText( (wchar_t *)lParam, (int)wParam );
+ case WM_NOTIFY:
+ {
+ LPTOOLTIPTEXTW tt = (LPTOOLTIPTEXTW)lParam;
+ if ( tt->hdr.hwndFrom = hTooltipWindow )
+ {
+ switch ( tt->hdr.code )
+ {
+ case TTN_SHOW:
+ SetWindowPos( tt->hdr.hwndFrom, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
+ break;
+ case TTN_NEEDTEXTW:
+ {
+ LPTOOLTIPTEXTW tt = (LPTOOLTIPTEXTW)lParam;
+ wchar_t booga[ 81 ] = { 0 };
+ GetWindowTextW( hwnd, booga, 79 );
+ booga[ 79 ] = 0;
+ StringCchCopyW( tt->szText, 80, booga );
+ tt->lpszText = tt->szText;
+ return 0;
+ }
+ }
+ }
+ break;
+ }
+ case WM_SETFOCUS:
+ if ( !config_mw_open )
+ {
+ if ( config_pe_open )
+ SetForegroundWindow( hPLWindow );
+ else if ( config_eq_open )
+ SetForegroundWindow( hEQWindow );
+ // else if (config_mb_open) SetForegroundWindow(hMBWindow);
+ else if ( config_video_open )
+ SetForegroundWindow( hVideoWindow );
+ else
+ {
+ EnterCriticalSection( &embedcs );
+ {
+ embedWindowState *p = embedwndlist;
+ while ( p )
+ {
+ if ( IsWindowVisible( p->me ) )
+ {
+ SetForegroundWindow( p->me );
+ break;
+ }
+
+ p = p->link;
+ }
+ }
+
+ LeaveCriticalSection( &embedcs );
+ }
+ }
+
+ break;
+ case WM_KILLFOCUS:
+ {
+ if ( !config_mw_open )
+ {
+ if ( config_pe_open )
+ SetForegroundWindow( hPLWindow );
+ else if ( config_eq_open )
+ SetForegroundWindow( hEQWindow );
+ // else if (config_mb_open) SetForegroundWindow(hMBWindow);
+ else if ( config_video_open )
+ SetForegroundWindow( hVideoWindow );
+ else
+ {
+ EnterCriticalSection( &embedcs );
+ {
+ embedWindowState *p = embedwndlist;
+ while ( p )
+ {
+ if ( IsWindowVisible( p->me ) )
+ {
+ SetForegroundWindow( p->me );
+ break;
+ }
+
+ p = p->link;
+ }
+ }
+
+ LeaveCriticalSection( &embedcs );
+ }
+ }
+
+
+ break;
+ }
+ case WM_MOUSEWHEEL:
+ {
+ // because some people don't like it
+ if ( config_nomwheel )
+ break;
+
+ int zDelta = GET_WHEEL_DELTA_WPARAM( wParam ), dLines;
+ // if the delta changes then ignore prior carryover
+ // hopefully this will go with the expected action.
+ if ( zDelta < 0 && main_delta_carryover > 0 || zDelta > 0 && main_delta_carryover < 0 )
+ main_delta_carryover = 0;
+ // otherwise add on the carryover from the prior message
+ else
+ zDelta += main_delta_carryover;
+
+ if ( 0 == ( MK_MBUTTON & LOWORD( wParam ) ) )
+ zDelta *= 2;
+
+ dLines = zDelta / WHEEL_DELTA;
+ main_delta_carryover = zDelta - dLines * WHEEL_DELTA;
+
+ if ( 0 != dLines )
+ {
+ zDelta = ( dLines > 0 ) ? dLines : -dLines;
+
+ if ( 0 != ( MK_MBUTTON & LOWORD( wParam ) ) )
+ {
+ if ( dLines >= 0 )
+ dLines = WINAMP_FFWD5S;
+ else
+ dLines = WINAMP_REW5S;
+ }
+ else
+ {
+ if ( dLines >= 0 )
+ dLines = WINAMP_VOLUMEUP;
+ else
+ dLines = WINAMP_VOLUMEDOWN;
+ }
+
+ while ( zDelta-- )
+ {
+ SendMessageW( hwnd, WM_COMMAND, dLines, 0 );
+ }
+ }
+ break;
+ }
+ case WM_DWMSENDICONICTHUMBNAIL:
+ {
+ int x = HIWORD( lParam );
+ int y = LOWORD( lParam );
+ OnIconicThumbnail( x, y );
+ }
+ break;
+#if 0
+ case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
+ {
+ //MessageBoxA(NULL, "winamp/live", "winamp/live", MB_OK);
+ OnThumbnailPreview();
+ }
+ break;
+#endif
+ case WM_MOVE:
+#if 0
+ if ( (int)LOWORD( lParam ) < 32768 && (int)HIWORD( lParam ) < 32768 )
+ {
+ if (/*(int)LOWORD(lParam) != 3000 && */(int)HIWORD( lParam ) != OFFSCREEN_Y_POS )
+ {
+ if ( (int)LOWORD( lParam ) != config_wx ||
+ (int)HIWORD( lParam ) != config_wy )
+ if ( config_keeponscreen & 1 )
+ {
+ config_wx = (int)LOWORD( lParam );
+ config_wy = (int)HIWORD( lParam );
+ set_aot( 1 );
+ }
+ }
+ }
+#endif
+ break;
+ case WM_SETCURSOR:
+
+ switch ( HIWORD( lParam ) )
+ {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ DisabledWindow_OnMouseClick( hwnd );
+ break;
+ }
+ if ( config_usecursors && !disable_skin_cursors )
+ {
+ if ( (HWND)wParam == hMainWindow && HIWORD( lParam ) == WM_MOUSEMOVE )
+ ui_handlecursor();
+
+ return TRUE;
+ }
+ else
+ SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
+
+ break;
+ }
+
+ return ( DefWindowProcW( hwnd, uMsg, wParam, lParam ) );
+}
+
+static LRESULT Main_OnSysCommand( HWND hwnd, UINT cmd, int x, int y )
+{
+ // char buf[512];
+ // wsprintf(buf,"got WM_SYSCOMMAND %08x\n",cmd);
+ // OutputDebugString(buf);
+ // video
+ if ( ( ( cmd & 0xfff0 ) == SC_SCREENSAVE || ( cmd & 0xfff0 ) == SC_MONITORPOWER ) && config_video_noss && video_isVideoPlaying() )
+ {
+ return -1;
+ }
+
+ if ( !Main_OnCommand( hwnd, cmd, (HWND)x, (UINT)y ) )
+ FORWARD_WM_SYSCOMMAND( hwnd, cmd, x, y, DefWindowProcW );
+ return 1;
+}
+
+static LRESULT WINAPI browseCheckBoxProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ if ( !( config_rofiob & 2 ) )
+ CheckDlgButton( hwndDlg, IDC_CHECK1, BST_CHECKED );
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ if ( LOWORD( wParam ) == IDC_CHECK1 )
+ {
+ config_rofiob &= ~2;
+ if ( !IsDlgButtonChecked( hwndDlg, IDC_CHECK1 ) )
+ config_rofiob |= 2;
+
+ config_write( 0 );
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+BOOL CALLBACK browseEnumProc( HWND hwnd, LPARAM lParam )
+{
+ char cl[ 32 ] = { 0 };
+ GetClassNameA( hwnd, cl, ARRAYSIZE( cl ) );
+ if ( !lstrcmpiA( cl, WC_TREEVIEWA ) )
+ {
+ PostMessageW( hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection( hwnd ) );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
+{
+ switch ( uMsg )
+ {
+ case BFFM_INITIALIZED:
+ {
+ SetWindowTextW( hwnd, getStringW( ( !lpData ? IDS_OPENDIR : IDS_ADD_FOLDER ), NULL, 0 ) );
+ SendMessageW( hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)config_cwd );
+
+ HWND h = FindWindowExW( hwnd, NULL, NULL, L"__foo" );
+ if ( h )
+ ShowWindow( h, SW_HIDE );
+
+ h = LPCreateDialogW( IDD_BROWSE_RECDLG, hwnd, browseCheckBoxProc );
+
+ SetWindowPos( h, 0, 4, 4, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+ ShowWindow( h, SW_SHOWNA );
+
+ // this is not nice but it fixes the selection not working correctly on all OSes
+ EnumChildWindows( hwnd, browseEnumProc, 0 );
+ }
+ }
+
+ return 0;
+}
+
+LRESULT sendMlIpc( int msg, WPARAM param )
+{
+ static LRESULT IPC_GETMLWINDOW;
+ static HWND mlwnd;
+
+ if ( !IPC_GETMLWINDOW ) IPC_GETMLWINDOW = wa_register_ipc( ( WPARAM ) & "LibraryGetWnd" );
+ if ( !mlwnd || (int)mlwnd == 1 )
+ mlwnd = (HWND)SendMessageW( hMainWindow, WM_WA_IPC, 0, IPC_GETMLWINDOW );
+
+ if ( param == 0 && msg == 0 ) return (LRESULT)mlwnd;
+
+ if ( IsWindow( mlwnd ) )
+ return SendMessageW( mlwnd, WM_ML_IPC, param, msg );
+
+ return 0;
+}
+
+void tealike_crappy_code( unsigned long v[ 2 ], unsigned long k[ 4 ] )
+{
+ unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0, /* set up */
+ delta = 0x9e3779b9UL, n = 32; /* key schedule constant*/
+
+ while ( n-- > 0 )
+ {
+ /* basic cycle start */
+ sum += delta;
+ y += ( ( z << 4 ) + k[ 0 ] ) ^ ( z + sum ) ^ ( ( z >> 5 ) + k[ 1 ] );
+ z += ( ( y << 4 ) + k[ 2 ] ) ^ ( y + sum ) ^ ( ( y >> 5 ) + k[ 3 ] ); /* end cycle */
+ }
+ v[ 0 ] = y; v[ 1 ] = z;
+}
+
+// command line parsing, for IPC or normal modes
+// goes to a lot of trouble to look for "'s.
+
+HWND find_otherwinamp( wchar_t *cmdline )
+{
+ int y = 0;
+ wchar_t buf[ MAX_PATH ] = { 0 };
+
+ StringCchPrintfW( buf, MAX_PATH, L"%s_%x_CLASS", szAppName, APP_VERSION_NUM );
+again:
+ g_hEventRunning = CreateEventW( 0, 1, 0, buf );
+ if ( g_hEventRunning && GetLastError() == ERROR_ALREADY_EXISTS )
+ {
+ int x;
+ CloseHandle( g_hEventRunning );
+ g_hEventRunning = 0;
+ // check for window for 4s, then give up
+ if ( !bNoHwndOther && ( !config_minst || *cmdline ) ) for ( x = 0; x < 40; x++ )
+ {
+ HWND lhwnd = NULL;
+ int failed = 0;
+ while ( ( lhwnd = FindWindowExW( NULL, lhwnd, szAppName, NULL ) ) )
+ {
+ DWORD_PTR vn = 0; //APP_VERSION_NUM
+ if ( lhwnd == hMainWindow )
+ continue;
+ if ( !SendMessageTimeout( lhwnd, WM_WA_IPC, 0, IPC_GETVERSION, SMTO_NORMAL, 5000, &vn ) )
+ {
+ failed = 1;
+ }
+ else if ( vn == APP_VERSION_NUM ) return lhwnd;
+ }
+ if ( failed ) return NULL; // no valid winamp windows, but one that fucked up
+
+ Sleep( 100 );
+ }
+ if ( y++ < 20 ) goto again;
+ }
+ return NULL;
+}
+
+
+// returns 0 if showing/hiding sould be aborted
+int Ipc_WindowToggle( INT_PTR which, INT_PTR how )
+{
+ return SendMessageW( hMainWindow, WM_WA_IPC, which, how ? IPC_CB_ONSHOWWND : IPC_CB_ONHIDEWND );
+}
+//}
+
+#ifdef BENSKI_TEST_WM_PRINTCLIENT
+static void PrintWindow( HWND hWnd )
+{
+ HDC hDCMem = CreateCompatibleDC( NULL );
+ HBITMAP hBmp = NULL;
+ RECT rect;
+
+ GetWindowRect( hWnd, &rect );
+ {
+ HDC hDC = GetDC( hWnd );
+ hBmp = CreateCompatibleBitmap( hDC, rect.right - rect.left, rect.bottom - rect.top );
+ ReleaseDC( hWnd, hDC );
+ }
+ {
+ HGDIOBJ hOld = SelectObject( hDCMem, hBmp );
+ SendMessageW( hWnd, WM_PRINT, (WPARAM)hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED );
+
+ SelectObject( hDCMem, hOld );
+ }
+ DeleteObject( hDCMem );
+
+ OpenClipboard( hWnd );
+
+ EmptyClipboard();
+ SetClipboardData( CF_BITMAP, hBmp );
+ CloseClipboard();
+}
+#endif \ No newline at end of file