aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/setup
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Winamp/setup')
-rw-r--r--Src/Winamp/setup/checkbox.bmpbin0 -> 886 bytes
-rw-r--r--Src/Winamp/setup/headerstrip.bmpbin0 -> 206 bytes
-rw-r--r--Src/Winamp/setup/httpgrab.cpp183
-rw-r--r--Src/Winamp/setup/httpgrab.h13
-rw-r--r--Src/Winamp/setup/ifc_setupjob.h42
-rw-r--r--Src/Winamp/setup/ifc_setuppage.h62
-rw-r--r--Src/Winamp/setup/langutil.cpp43
-rw-r--r--Src/Winamp/setup/langutil.h18
-rw-r--r--Src/Winamp/setup/loadimage.cpp235
-rw-r--r--Src/Winamp/setup/loadimage.h12
-rw-r--r--Src/Winamp/setup/navitemstrip.bmpbin0 -> 182 bytes
-rw-r--r--Src/Winamp/setup/navstrip.bmpbin0 -> 1278 bytes
-rw-r--r--Src/Winamp/setup/png.rc72
-rw-r--r--Src/Winamp/setup/postsetup.cpp68
-rw-r--r--Src/Winamp/setup/postsetup.h10
-rw-r--r--Src/Winamp/setup/preview_classic.pngbin0 -> 16177 bytes
-rw-r--r--Src/Winamp/setup/preview_no.pngbin0 -> 3941 bytes
-rw-r--r--Src/Winamp/setup/resource.h16
-rw-r--r--Src/Winamp/setup/setup.cpp1131
-rw-r--r--Src/Winamp/setup/setup.h66
-rw-r--r--Src/Winamp/setup/setup.rc446
-rw-r--r--Src/Winamp/setup/setup_api.h24
-rw-r--r--Src/Winamp/setup/setup_resource.h139
-rw-r--r--Src/Winamp/setup/setupcommon.h31
-rw-r--r--Src/Winamp/setup/setupfactory.cpp249
-rw-r--r--Src/Winamp/setup/setupfactory.h19
-rw-r--r--Src/Winamp/setup/sjob_register.cpp84
-rw-r--r--Src/Winamp/setup/sjob_register.h28
-rw-r--r--Src/Winamp/setup/skininfo.cpp330
-rw-r--r--Src/Winamp/setup/skininfo.h38
-rw-r--r--Src/Winamp/setup/smokingllama.pngbin0 -> 1581 bytes
-rw-r--r--Src/Winamp/setup/spage_assoc.cpp1069
-rw-r--r--Src/Winamp/setup/spage_assoc.h57
-rw-r--r--Src/Winamp/setup/spage_connect.cpp313
-rw-r--r--Src/Winamp/setup/spage_connect.h45
-rw-r--r--Src/Winamp/setup/spage_feedback.cpp392
-rw-r--r--Src/Winamp/setup/spage_feedback.h45
-rw-r--r--Src/Winamp/setup/spage_lang.cpp293
-rw-r--r--Src/Winamp/setup/spage_lang.h42
-rw-r--r--Src/Winamp/setup/spage_skin.cpp646
-rw-r--r--Src/Winamp/setup/spage_skin.h52
-rw-r--r--Src/Winamp/setup/svc_setup.h123
-rw-r--r--Src/Winamp/setup/wa_classic_preview.pngbin0 -> 16177 bytes
43 files changed, 6436 insertions, 0 deletions
diff --git a/Src/Winamp/setup/checkbox.bmp b/Src/Winamp/setup/checkbox.bmp
new file mode 100644
index 00000000..4730c42b
--- /dev/null
+++ b/Src/Winamp/setup/checkbox.bmp
Binary files differ
diff --git a/Src/Winamp/setup/headerstrip.bmp b/Src/Winamp/setup/headerstrip.bmp
new file mode 100644
index 00000000..a40b51dd
--- /dev/null
+++ b/Src/Winamp/setup/headerstrip.bmp
Binary files differ
diff --git a/Src/Winamp/setup/httpgrab.cpp b/Src/Winamp/setup/httpgrab.cpp
new file mode 100644
index 00000000..6f45914a
--- /dev/null
+++ b/Src/Winamp/setup/httpgrab.cpp
@@ -0,0 +1,183 @@
+#include "main.h"
+#include "./httpgrab.h"
+
+
+static HHOOK g_hook = NULL;
+static HWND g_hook_host = NULL;
+static HWND g_hook_fwd = NULL;
+static DWORD g_hook_flags = 0;
+static HWND *g_hook_phwnd =NULL;
+
+static LRESULT CALLBACK TargetWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK LabelWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+static BOOL IsDialog(HWND hwnd)
+{
+ wchar_t szName[256] = {0};
+ return (GetClassNameW(hwnd, szName, sizeof(szName)/sizeof(wchar_t)) &&
+ CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+ NORM_IGNORECASE, szName, -1, L"#32770", -1));
+}
+
+static LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
+{
+ if (HCBT_CREATEWND == code && IsDialog((HWND)wParam) && ((CBT_CREATEWND*)lParam)->lpcs->hwndParent == g_hook_host)
+ {
+ LRESULT result;
+
+ result = CallNextHookEx(g_hook, code, wParam, lParam);
+ UnhookWindowsHookEx(g_hook);
+ g_hook = NULL;
+
+ if (0 == result)
+ {
+ ((CBT_CREATEWND*)lParam)->lpcs->style &= ~WS_VISIBLE;
+ WNDPROC oldProc = (WNDPROC)SetWindowLongPtrW((HWND)wParam, GWLP_WNDPROC, (LONG_PTR)TargetWndProc);
+ if (oldProc)
+ {
+ SetPropW((HWND)wParam, L"WNDPROC", oldProc);
+ if (g_hook_fwd) SetPropW((HWND)wParam, L"FWDHWND", g_hook_fwd);
+ if (g_hook_flags) SetPropW((HWND)wParam, L"FLAGS", (HANDLE)(INT_PTR)g_hook_flags);
+ if (g_hook_phwnd) *g_hook_phwnd = (HWND)wParam;
+ }
+ }
+ else if (g_hook_host && IsWindow(g_hook_host)) DestroyWindow(g_hook_host);
+
+ g_hook_fwd = NULL;
+ g_hook_flags = 0;
+ g_hook_host = NULL;
+ return result;
+ }
+ return CallNextHookEx(g_hook, code, wParam, lParam);
+}
+
+HWND BeginGrabHTTPText(HWND hwndFwd, UINT flags, HWND *phwndTarget)
+{
+
+ g_hook_host = CreateWindowExW(0x08000000/*WS_EX_NOACTIVATE*/ | WS_EX_NOPARENTNOTIFY, L"STATIC", L"", WS_DISABLED | WS_POPUP, -10000, -10000, 0, 0, NULL, NULL, NULL, NULL);
+ if (!g_hook_host) return NULL;
+
+ g_hook = SetWindowsHookEx(WH_CBT, HookProc, NULL, GetCurrentThreadId());
+ if (!g_hook)
+ {
+ if (g_hook_host) DestroyWindow(g_hook_host);
+ g_hook_host = NULL;
+ g_hook_fwd = NULL;
+ g_hook_flags = 0;
+ g_hook_phwnd = NULL;
+ }
+ else
+ {
+ g_hook_fwd = hwndFwd;
+ g_hook_flags = flags;
+ g_hook_phwnd = phwndTarget;
+ }
+ return g_hook_host;
+}
+
+void EndGrabHTTPText(HWND hwndHost)
+{
+ if (g_hook_host == hwndHost)
+ {
+ if (g_hook) UnhookWindowsHookEx(g_hook);
+ g_hook = NULL;
+ g_hook_host = NULL;
+ g_hook_fwd = NULL;
+ g_hook_flags = 0;
+ }
+ if (IsWindow(hwndHost)) DestroyWindow(hwndHost);
+}
+
+static LRESULT CALLBACK TargetWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"WNDPROC");
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ HWND hwndFwd;
+
+ hwndFwd = (HWND)GetPropW(hwnd, L"FWDHWND");
+ DWORD flags = (DWORD)(INT_PTR)GetPropW(hwnd, L"FLAGS");
+ RemovePropW(hwnd, L"FLAGS");
+ RemovePropW(hwnd, L"FWDHWND");
+
+ if (hwndFwd)
+ {
+ HWND hwndText;
+ if (HTTPGRAB_USESTATUSTEXT & flags)
+ {
+ hwndText = GetDlgItem(hwnd, 1180/*IDC_STATUS*/);
+ WNDPROC oldProc = (WNDPROC)SetWindowLongPtrW(hwndText, GWLP_WNDPROC, (LONG_PTR)LabelWndProc);
+ if (oldProc) SetPropW(hwndText, L"WNDPROC", oldProc);
+ else hwndText = hwnd;
+ }
+ else hwndText = hwnd;
+ SetPropW(hwndText, L"FWDTEXT", hwndFwd);
+
+ WCHAR szText[256] = {0};
+ GetWindowTextW(hwndText, szText, sizeof(szText)/sizeof(wchar_t));
+ SetWindowTextW(hwndFwd, szText);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ RemovePropW(hwnd, L"WNDPROC");
+ RemovePropW(hwnd, L"FWDTEXT");
+ if (fnOldProc) SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc);
+ HWND hwndOwner;
+ hwndOwner = GetWindow(hwnd, GW_OWNER);
+ if (hwndOwner) DestroyWindow(hwndOwner);
+ }
+ break;
+ case WM_STYLECHANGING:
+ if (GWL_STYLE & wParam) ((STYLESTRUCT*)lParam)->styleNew &= ~WS_VISIBLE;
+ return 0;
+ case WM_STYLECHANGED:
+ if ((GWL_STYLE & wParam) && (WS_VISIBLE & ((STYLESTRUCT*)lParam)->styleNew))
+ SetWindowLongPtrW(hwnd, GWL_STYLE, (((STYLESTRUCT*)lParam)->styleNew & ~WS_VISIBLE));
+ return 0;
+ case WM_WINDOWPOSCHANGING:
+ ((WINDOWPOS*)lParam)->flags = (((WINDOWPOS*)lParam)->flags & ~(SWP_SHOWWINDOW | SWP_FRAMECHANGED)) | SWP_NOACTIVATE | SWP_NOZORDER;
+ return 0;
+ case WM_SETTEXT:
+ {
+ HWND hwndFwd = (HWND)GetPropW(hwnd, L"FWDTEXT");
+ if (hwndFwd)
+ {
+ (IsWindowUnicode(hwndFwd)) ? SendMessageW(hwndFwd, WM_SETTEXT, wParam, lParam) :
+ SendMessageA(hwndFwd, WM_SETTEXT, wParam, lParam);
+ }
+ }
+ break;
+ }
+ if (!fnOldProc) return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ return (IsWindowUnicode(hwnd)) ? CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnOldProc, hwnd, uMsg, wParam, lParam);
+}
+
+static LRESULT CALLBACK LabelWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"WNDPROC");
+
+ switch(uMsg)
+ {
+ case WM_SETTEXT:
+ {
+ HWND hwndFwd = (HWND)GetPropW(hwnd, L"FWDTEXT");
+ if (hwndFwd)
+ {
+ (IsWindowUnicode(hwndFwd)) ? SendMessageW(hwndFwd, WM_SETTEXT, wParam, lParam) :
+ SendMessageA(hwndFwd, WM_SETTEXT, wParam, lParam);
+ }
+ }
+ case WM_DESTROY:
+ RemovePropW(hwnd, L"WNDPROC");
+ RemovePropW(hwnd, L"FWDTEXT");
+ if (fnOldProc) SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc);
+ break;
+ }
+ if (!fnOldProc) return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ return (IsWindowUnicode(hwnd)) ? CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnOldProc, hwnd, uMsg, wParam, lParam);
+}
diff --git a/Src/Winamp/setup/httpgrab.h b/Src/Winamp/setup/httpgrab.h
new file mode 100644
index 00000000..94845df8
--- /dev/null
+++ b/Src/Winamp/setup/httpgrab.h
@@ -0,0 +1,13 @@
+#ifndef WINAMP_HTTP_GRAB_TEXT_HEADER
+#define WINAMP_HTTP_GRAB_TEXT_HEADER
+
+#include <windows.h>
+
+#define HTTPGRAB_USEWINDOWTEXT 0x0000
+#define HTTPGRAB_USESTATUSTEXT 0x0001
+
+HWND BeginGrabHTTPText(HWND hwndFwd, UINT flags, HWND *phwndTarget); // returns hwnd that you need to supply as parent of http funciton
+void EndGrabHTTPText(HWND hwndHost);
+
+
+#endif //WINAMP_HTTP_GRAB_TEXT_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/ifc_setupjob.h b/Src/Winamp/setup/ifc_setupjob.h
new file mode 100644
index 00000000..ae239810
--- /dev/null
+++ b/Src/Winamp/setup/ifc_setupjob.h
@@ -0,0 +1,42 @@
+#ifndef WINAMP_IFC_SETUP_JOB_HEADER
+#define WINAMP_IFC_SETUP_JOB_HEADER
+
+#include <bfc/dispatch.h>
+#include <windows.h>
+
+class NOVTABLE ifc_setupjob : public Dispatchable
+{
+protected:
+ ifc_setupjob(void) {}
+ virtual ~ifc_setupjob(void) {}
+
+public:
+ HRESULT Execute(HWND hwndText);
+ HRESULT Cancel(HWND hwndText);
+ HRESULT IsCancelSupported(void);
+
+public:
+ DISPATCH_CODES
+ {
+ API_SETUPJOB_EXECUTE = 10,
+ API_SETUPJOB_CANCEL = 20,
+ API_SETUPJOB_ISCANCELSUPPORTED = 30,
+ };
+};
+
+inline HRESULT ifc_setupjob::Execute(HWND hwndText)
+{
+ return _call(API_SETUPJOB_EXECUTE, E_NOTIMPL, hwndText);
+}
+
+inline HRESULT ifc_setupjob::Cancel(HWND hwndText)
+{
+ return _call(API_SETUPJOB_CANCEL, E_NOTIMPL, hwndText);
+}
+
+inline HRESULT ifc_setupjob::IsCancelSupported(void)
+{
+ return _call(API_SETUPJOB_ISCANCELSUPPORTED, E_NOTIMPL);
+}
+
+#endif //WINAMP_IFC_SETUP_JOB_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/ifc_setuppage.h b/Src/Winamp/setup/ifc_setuppage.h
new file mode 100644
index 00000000..3ea57de8
--- /dev/null
+++ b/Src/Winamp/setup/ifc_setuppage.h
@@ -0,0 +1,62 @@
+#ifndef WINAMP_IFC_SETUP_PAGE_HEADER
+#define WINAMP_IFC_SETUP_PAGE_HEADER
+
+#include <bfc/dispatch.h>
+#include <windows.h>
+
+class NOVTABLE ifc_setuppage : public Dispatchable
+{
+protected:
+ ifc_setuppage(void) {}
+ virtual ~ifc_setuppage(void) {}
+
+public:
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText); // setup will allways call this no matter of IsDirty result. (you can check dirty state inside save());
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void); // S_OK - valid, S_FALSE - page is not dirty ( no save required), E_NOTIMPL - not impl. all errors counts as dirty
+ HRESULT Validate(void); // S_OK - valid, S_FALSE - invalid, E_NOTIMPL - not impl. all errors counts as page is valid
+
+public:
+ DISPATCH_CODES
+ {
+ API_SETUPPAGE_GET_NAME = 10,
+ API_SETUPPAGE_CREATEVIEW = 20,
+ API_SETUPPAGE_SAVE = 30,
+ API_SETUPPAGE_ISDIRTY = 40,
+ API_SETUPPAGE_REVERT = 50,
+ API_SETUPPAGE_VALIDATE = 60,
+ };
+};
+
+inline HRESULT ifc_setuppage::GetName(bool bShort, const wchar_t **pszName)
+{
+ return _call(API_SETUPPAGE_GET_NAME, E_NOTIMPL, bShort, pszName);
+}
+
+inline HRESULT ifc_setuppage::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ return _call(API_SETUPPAGE_CREATEVIEW, E_NOTIMPL, hwndParent, phwnd);
+}
+
+inline HRESULT ifc_setuppage::Save(HWND hwndText)
+{
+ return _call(API_SETUPPAGE_SAVE, E_NOTIMPL, hwndText);
+}
+
+inline HRESULT ifc_setuppage::IsDirty(void)
+{
+ return _call(API_SETUPPAGE_ISDIRTY, E_NOTIMPL);
+}
+
+inline HRESULT ifc_setuppage::Revert(void)
+{
+ return _call(API_SETUPPAGE_REVERT, E_NOTIMPL);
+}
+
+inline HRESULT ifc_setuppage::Validate(void)
+{
+ return _call(API_SETUPPAGE_VALIDATE, E_NOTIMPL);
+}
+#endif //WINAMP_IFC_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/langutil.cpp b/Src/Winamp/setup/langutil.cpp
new file mode 100644
index 00000000..a461fc3b
--- /dev/null
+++ b/Src/Winamp/setup/langutil.cpp
@@ -0,0 +1,43 @@
+#include "main.h"
+#include "./langutil.h"
+
+
+
+INT_PTR WADialogBoxParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+ INT_PTR ret(0);
+ HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance;
+ while(hInst)
+ {
+ ret = DialogBoxParamW(hInst, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
+ if (-1 == ret && hInst != hMainInstance) hInst = hMainInstance;
+ else break;
+ }
+ return ret;
+}
+
+HWND WACreateDialogParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+ HWND ret(NULL);
+ HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance;
+ while(hInst)
+ {
+ ret = CreateDialogParamW(hInst, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
+ if (NULL == ret && hInst != hMainInstance) hInst = hMainInstance;
+ else break;
+ }
+ return ret;
+}
+
+HBITMAP WALoadImage2(LPCWSTR pszSectionName, LPCWSTR lpImageName, BOOL bPremult)
+{
+ HBITMAP ret(NULL);
+ HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance;
+ while(hInst)
+ {
+ ret = WALoadImage(hInst, pszSectionName, lpImageName, bPremult);
+ if (NULL == ret && hInst != hMainInstance) hInst = hMainInstance;
+ else break;
+ }
+ return ret;
+} \ No newline at end of file
diff --git a/Src/Winamp/setup/langutil.h b/Src/Winamp/setup/langutil.h
new file mode 100644
index 00000000..dc4168de
--- /dev/null
+++ b/Src/Winamp/setup/langutil.h
@@ -0,0 +1,18 @@
+#ifndef WINAMP_SETUP_LANGUTIL_HEADER
+#define WINAMP_SETUP_LANGUTIL_HEADER
+
+#include <windows.h>
+#include "./loadimage.h"
+
+INT_PTR WADialogBoxParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+HWND WACreateDialogParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+HBITMAP WALoadImage2(LPCWSTR pszSectionName, LPCWSTR lpImageName, BOOL bPremult);
+
+
+#define WADialogBox(lpTemplate, hWndParent, lpDialogFunc) \
+WADialogBoxParam(lpTemplate, hWndParent, lpDialogFunc, 0L)
+
+#define WACreateDialog(lpName, hWndParent, lpDialogFunc) \
+WACreateDialogParam(lpName, hWndParent, lpDialogFunc, 0L)
+
+#endif //WINAMP_SETUP_LANGUTIL_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/loadimage.cpp b/Src/Winamp/setup/loadimage.cpp
new file mode 100644
index 00000000..54bbe566
--- /dev/null
+++ b/Src/Winamp/setup/loadimage.cpp
@@ -0,0 +1,235 @@
+#include "main.h"
+#include "./loadimage.h"
+#include "./api.h"
+#include <api/service/waServiceFactory.h>
+#include <api/service/svcs/svc_imgload.h>
+
+#define ABS(x) (((x) > 0) ? (x) : (-x))
+
+static HANDLE ReadFromFile(LPCWSTR pszImage, DWORD *size, HANDLE *hres)
+{
+ HANDLE hFile = CreateFileW(pszImage, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL), hmem(NULL);
+ *size = 0;
+ if (INVALID_HANDLE_VALUE != hFile)
+ {
+ *size = GetFileSize(hFile, NULL);
+ if (INVALID_FILE_SIZE != *size)
+ {
+ hmem = HeapAlloc(GetProcessHeap(), 0, *size);
+ if (hmem)
+ {
+ DWORD readed = 0;
+ if (!ReadFile(hFile, hmem, *size, &readed, NULL) || *size != readed)
+ {
+ HeapFree(GetProcessHeap(), 0, hmem);
+ hmem = NULL;
+ }
+ }
+ }
+ CloseHandle(hFile);
+ }
+
+ *hres = hmem;
+ return hmem;
+}
+
+static HANDLE ReadFromRes(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, DWORD *size, HANDLE *hres)
+{
+ *size = 0;
+ HRSRC res = FindResourceW(hMod, pszImage, pszSection);
+ if (res)
+ {
+ *hres = LoadResource(hMod, res);
+ *size = SizeofResource(hMod, res);
+ return LockResource(*hres);
+ }
+ return NULL;
+}
+
+static HANDLE LoadImg(HANDLE data, DWORD size, INT *cx, INT *cy, BOOL premult)
+{
+ FOURCC imgload = svc_imageLoader::getServiceType();
+ int n = (int) WASABI_API_SVC->service_getNumServices(imgload);
+ for (int i=0; i<n; i++)
+ {
+ waServiceFactory *sf = WASABI_API_SVC->service_enumService(imgload,i);
+ if (sf)
+ {
+ svc_imageLoader * l = (svc_imageLoader*)sf->getInterface();
+ if (l)
+ {
+ if (l->testData(data,size))
+ {
+ HANDLE ret;
+ ret = (premult) ? l->loadImage(data, size, cx, cy) : l->loadImageData(data, size, cx, cy);
+ sf->releaseInterface(l);
+ return ret;
+ }
+ sf->releaseInterface(l);
+ }
+ }
+ }
+ return NULL;
+}
+
+HBITMAP WALoadImage(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, BOOL bPremult)
+{
+ BITMAPINFOHEADER header = {0};
+ HBITMAP hbmp = NULL;
+ HANDLE hres = NULL;
+ LPVOID dib = NULL;
+ DWORD size = 0;
+
+ header.biBitCount = 32;
+ header.biPlanes = 1;
+ header.biSize = sizeof(BITMAPINFOHEADER);
+
+ LPVOID data = (!hMod) ? ReadFromFile(pszImage, &size, &hres) : ReadFromRes(hMod, pszSection, pszImage, &size, &hres);
+
+ if (data) data = LoadImg(data, size, (int*)&header.biWidth, (int*)&header.biHeight, bPremult);
+
+ if (hres)
+ {
+ (hMod) ? FreeResource(hres) : HeapFree(GetProcessHeap(), 0, hres);
+ }
+
+ if (data)
+ {
+ header.biHeight = 0 - header.biHeight;
+ hbmp = CreateDIBSection(NULL, (LPBITMAPINFO)&header, DIB_RGB_COLORS, &dib, NULL, 0);
+ if (hbmp) CopyMemory(dib, data, header.biWidth * ABS(header.biHeight) * sizeof(DWORD));
+ WASABI_API_MEMMGR->sysFree(data);
+ }
+ else hbmp = NULL;
+ return hbmp;
+}
+
+HBITMAP WAResizeImage(HBITMAP hbmp, INT cx, INT cy, HBRUSH hbBk)
+{
+ BITMAP bi = {0};
+
+ if (!hbmp || !GetObject(hbmp, sizeof(BITMAP), &bi)) return hbmp;
+
+ if (bi.bmWidth != cx || bi.bmHeight != cy)
+ {
+ INT ix = cx, iy = cy;
+
+ HDC hdc = GetDC(NULL),
+ hdcSrc = CreateCompatibleDC(hdc),
+ hdcDst = CreateCompatibleDC(hdc);
+ HBITMAP hbmpOld1 = (HBITMAP)SelectObject(hdcSrc, hbmp);
+ hbmp = CreateCompatibleBitmap(hdc, cx, cy);
+ HBITMAP hbmpOld2 = (HBITMAP)SelectObject(hdcDst, hbmp);
+ if (ix != cx || iy != cy)
+ {
+ RECT r;
+ SetRect(&r, 0, 0, cx, cy);
+ FillRect(hdcDst, &r, hbBk);
+ }
+ SetStretchBltMode(hdcDst, HALFTONE);
+ StretchBlt(hdcDst, (cx - ix)/2, (cy - iy)/2, ix, iy, hdcSrc, 0, 0, bi.bmWidth, bi.bmHeight, SRCCOPY);
+
+ SelectObject(hdcDst, hbmpOld2);
+ hbmpOld2 = (HBITMAP)SelectObject(hdcSrc, hbmpOld1);
+ if (hbmpOld2) DeleteObject(hbmpOld2);
+
+ DeleteDC(hdcSrc);
+ DeleteDC(hdcDst);
+ ReleaseDC(NULL, hdc);
+ }
+ return hbmp;
+}
+
+HBITMAP WABlendOnColor(HBITMAP hbmp, COLORREF rgbBk)
+{
+ DIBSECTION dibsec = {0};
+ LONG pitch, x;
+ INT cx, cy;
+ LPBYTE cursor = NULL, line = NULL, pData = NULL;
+
+ if (!hbmp || sizeof(DIBSECTION) != GetObjectW(hbmp, sizeof(DIBSECTION), &dibsec) ||
+ BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || 32 != dibsec.dsBm.bmBitsPixel) return hbmp;
+
+ cx = dibsec.dsBm.bmWidth;
+ cy = dibsec.dsBm.bmHeight;
+ pitch = dibsec.dsBm.bmWidth*4;
+ pData = (LPBYTE)dibsec.dsBm.bmBits;
+
+ for (line = pData; cy-- != 0; line += pitch )
+ {
+ for (x = cx, cursor = line; x-- != 0; cursor += 4)
+ {
+ if (0x00 == cursor[3])
+ {
+ cursor[0] = GetBValue(rgbBk);
+ cursor[1] = GetGValue(rgbBk);
+ cursor[2] = GetRValue(rgbBk);
+ cursor[3] = 0xFF;
+ }
+ else if (cursor[3] != 0xFF)
+ {
+ cursor[0] = (cursor[0]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetBValue(rgbBk) + 127)/255;
+ cursor[1] = (cursor[1]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetGValue(rgbBk) + 127)/255;
+ cursor[2] = (cursor[2]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetRValue(rgbBk) + 127)/255;
+ cursor[3] = 0xFF;
+ }
+ }
+ }
+ return hbmp;
+}
+
+HBITMAP WACreatePatternBitmap(INT cx, INT cy, INT bpp, HBRUSH hbPattern, LPBYTE *ppData)
+{
+ BITMAPINFOHEADER bi = {0};
+ RECT r;
+ HDC hdcTmp = CreateCompatibleDC(NULL);
+
+ bi.biSize = sizeof (bi);
+ bi.biWidth= cx;
+ bi.biHeight = -cy;
+ bi.biPlanes = 1;
+ bi.biBitCount= (WORD)bpp;
+
+ HBITMAP hbmpPattern = CreateDIBSection(hdcTmp, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (LPVOID*)ppData, NULL, NULL);
+ if (!hbmpPattern) return NULL;
+
+ HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcTmp, hbmpPattern);
+ SetRect(&r, 0, 0, cx, cy);
+ FillRect(hdcTmp, &r, hbPattern);
+ SelectObject(hdcTmp, hbmpOld);
+ DeleteDC(hdcTmp);
+ return hbmpPattern;
+}
+
+HBITMAP WABlendOnARGB32(HBITMAP hbmp, LPBYTE pRGB)
+{
+ DIBSECTION dibsec = {0};
+ LONG pitch, x;
+ INT cx, cy;
+ LPBYTE cursor = NULL, cursor2 = NULL, line = NULL, line2 = NULL, pData = NULL;
+
+ if (!hbmp || sizeof(DIBSECTION) != GetObjectW(hbmp, sizeof(DIBSECTION), &dibsec) ||
+ BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || 32 != dibsec.dsBm.bmBitsPixel) return hbmp;
+
+ cx = dibsec.dsBm.bmWidth;
+ cy = dibsec.dsBm.bmHeight;
+ pitch = dibsec.dsBm.bmWidth*4;
+ pData = (LPBYTE)dibsec.dsBm.bmBits;
+
+ for (line = pData, line2 = pRGB; cy-- != 0; line += pitch, line2 += pitch )
+ {
+ for (x = cx, cursor = line, cursor2 = line2; x-- != 0; cursor += 4, cursor2 += 4)
+ {
+ if (0x00 == cursor[3]) *((DWORD*)cursor) = *((DWORD*)cursor2);
+ else if (cursor[3] != 0xFF)
+ {
+ cursor[0] = (cursor[0]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[0] + 127)/255;
+ cursor[1] = (cursor[1]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[1] + 127)/255;
+ cursor[2] = (cursor[2]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[2] + 127)/255;
+ }
+ cursor[3] = 0xFF;
+ }
+ }
+
+ return hbmp;
+} \ No newline at end of file
diff --git a/Src/Winamp/setup/loadimage.h b/Src/Winamp/setup/loadimage.h
new file mode 100644
index 00000000..eb873753
--- /dev/null
+++ b/Src/Winamp/setup/loadimage.h
@@ -0,0 +1,12 @@
+#ifndef WINAMP_LOADIMAGE_HEADER
+#define WINAMP_LOADIMAGE_HEADER
+
+#include <windows.h>
+
+HBITMAP WALoadImage(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, BOOL bPremult);
+HBITMAP WAResizeImage(HBITMAP hbmp, INT cx, INT cy, HBRUSH hbBk);
+HBITMAP WABlendOnColor(HBITMAP hbmp, COLORREF rgbBk);
+HBITMAP WABlendOnARGB32(HBITMAP hbmp, LPBYTE pRGB);
+HBITMAP WACreatePatternBitmap(INT cx, INT cy, INT bpp, HBRUSH hbPattern, LPBYTE *ppData);
+
+#endif //WINAMP_LOADIMAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/navitemstrip.bmp b/Src/Winamp/setup/navitemstrip.bmp
new file mode 100644
index 00000000..0eb654ce
--- /dev/null
+++ b/Src/Winamp/setup/navitemstrip.bmp
Binary files differ
diff --git a/Src/Winamp/setup/navstrip.bmp b/Src/Winamp/setup/navstrip.bmp
new file mode 100644
index 00000000..6105816d
--- /dev/null
+++ b/Src/Winamp/setup/navstrip.bmp
Binary files differ
diff --git a/Src/Winamp/setup/png.rc b/Src/Winamp/setup/png.rc
new file mode 100644
index 00000000..e66ee65c
--- /dev/null
+++ b/Src/Winamp/setup/png.rc
@@ -0,0 +1,72 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "setup_resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Data
+//
+
+IDB_ABOUT ".\\smokingllama.png"
+IDB_PREVIEW_CLASSIC ".\\preview_classicskin.png"
+IDB_PREVIEW_NO_1 ".\\preview_no.png"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""setup_resource.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Winamp/setup/postsetup.cpp b/Src/Winamp/setup/postsetup.cpp
new file mode 100644
index 00000000..55eafa94
--- /dev/null
+++ b/Src/Winamp/setup/postsetup.cpp
@@ -0,0 +1,68 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include ".\postsetup.h"
+#include "./setup_resource.h"
+#include "./langutil.h"
+#include "api.h"
+
+
+static BOOL SleepMsg(DWORD dwTimeout)
+{
+ DWORD dwStart = GetTickCount();
+ DWORD dwElapsed;
+ while ((dwElapsed = GetTickCount() - dwStart) < dwTimeout)
+ {
+ DWORD dwStatus = MsgWaitForMultipleObjectsEx(0, NULL, dwTimeout - dwElapsed, QS_ALLINPUT, MWMO_WAITALL | MWMO_INPUTAVAILABLE);
+ if (dwStatus == WAIT_OBJECT_0) while (application->app_messageLoopStep());
+ }
+ return TRUE; // timed out
+}
+
+BOOL StartWinamp(BOOL bWaitShow, HWND *phwndWA, LPCSTR pszParam)
+{
+ HWND hwndWA;
+ DWORD pid;
+ wchar_t buf[MAX_PATH] = L"\"";
+ STARTUPINFOW si = {sizeof(si), };
+ PROCESS_INFORMATION pi;
+
+ if (phwndWA) *phwndWA = NULL;
+
+ GetModuleFileNameW(NULL, buf + 1, sizeof(buf)/sizeof(wchar_t) - 1);
+ StringCchCatW(buf, MAX_PATH, L"\" /NEW ");
+ if (*pszParam && lstrlenA(pszParam))
+ {
+ int count, len;
+ len = sizeof(buf)/sizeof(wchar_t) - lstrlenW(buf)- 1;
+ count = MultiByteToWideChar(CP_ACP, 0, pszParam, -1, NULL, 0);
+ if (count < len) MultiByteToWideChar(CP_ACP, 0, pszParam, -1, buf + lstrlenW(buf), len);
+ }
+ si.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOWNOACTIVATE;
+ if ( 0 ==CreateProcessW(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ return FALSE;
+ }
+
+ hwndWA = NULL;
+ if (bWaitShow)
+ {
+ for (int a = 0; a < 20; a++)
+ {
+ if (!hwndWA)
+ {
+ while (NULL != (hwndWA = FindWindowExW(NULL, hwndWA, szAppName, NULL)))
+ {
+ GetWindowThreadProcessId(hwndWA, &pid);
+ if (pid == pi.dwProcessId) break;
+ }
+ }
+ SleepMsg(250);
+ if (hwndWA && IsWindowVisible(hwndWA))
+ break;
+ }
+ }
+
+ if (phwndWA) *phwndWA = hwndWA;
+ return TRUE;
+} \ No newline at end of file
diff --git a/Src/Winamp/setup/postsetup.h b/Src/Winamp/setup/postsetup.h
new file mode 100644
index 00000000..001ed6ae
--- /dev/null
+++ b/Src/Winamp/setup/postsetup.h
@@ -0,0 +1,10 @@
+#ifndef WINAMP_POSTSETUP_HEADER
+#define WINAMP_POSTSETUP_HEADER
+
+#include <windows.h>
+
+HWND CreateStatusWnd(HWND hwndParent, INT x, INT y, INT cx, INT cy);
+void SetStatusText();
+BOOL StartWinamp(BOOL bWaitShow, HWND *phwndWA, LPCSTR pszParam);
+
+#endif //WINAMP_POSTSETUP_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/preview_classic.png b/Src/Winamp/setup/preview_classic.png
new file mode 100644
index 00000000..7a02a1da
--- /dev/null
+++ b/Src/Winamp/setup/preview_classic.png
Binary files differ
diff --git a/Src/Winamp/setup/preview_no.png b/Src/Winamp/setup/preview_no.png
new file mode 100644
index 00000000..317bc0ab
--- /dev/null
+++ b/Src/Winamp/setup/preview_no.png
Binary files differ
diff --git a/Src/Winamp/setup/resource.h b/Src/Winamp/setup/resource.h
new file mode 100644
index 00000000..7a1e3e2c
--- /dev/null
+++ b/Src/Winamp/setup/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by png.rc
+//
+#define IDB_PREVIEW_NO_1 115
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 117
+#define _APS_NEXT_COMMAND_VALUE 40017
+#define _APS_NEXT_CONTROL_VALUE 1033
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/Winamp/setup/setup.cpp b/Src/Winamp/setup/setup.cpp
new file mode 100644
index 00000000..4ec461ae
--- /dev/null
+++ b/Src/Winamp/setup/setup.cpp
@@ -0,0 +1,1131 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./setup.h"
+#include "./setup_resource.h"
+#include "./loadimage.h"
+#include "./langutil.h"
+#include "../nu/AutoWide.h"
+#include "api.h"
+
+#define HEADER_FONT_NAME "Arial"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS"
+#define HEADER_FONT_SIZE 13 //11
+#define HEADER_FONT_ITALIC FALSE
+#define HEADER_FONT_WEIGHT FW_MEDIUM
+#define HEADER_TEXT_COLOR RGB(255,255,255)//RGB(16, 72, 148)//RGB(7, 30, 140)
+#define HEADER_BORDER_COLOR RGB(236, 233, 216)
+
+#define HEADER_PAGENUM_FONT_NAME "Lucida Sans Unicode"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS"
+#define HEADER_PAGENUM_FONT_SIZE 10
+#define HEADER_PAGENUM_FONT_ITALIC FALSE
+#define HEADER_PAGENUM_FONT_WEIGHT FW_SEMIBOLD//FW_MEDIUM
+#define HEADER_PAGENUM_TEXT_COLOR RGB(210,120,42)
+
+#define NAVIGATION_FONT_NAME "Arial"
+#define NAVIGATION_FONT_SIZE 9
+#define NAVIGATION_FONT_ITALIC FALSE
+#define NAVIGATION_FONT_WEIGHT FW_MEDIUM
+
+#define NAVIGATION_SEL_FONT_NAME "Arial"
+#define NAVIGATION_SEL_FONT_SIZE 10
+#define NAVIGATION_SEL_FONT_ITALIC FALSE
+#define NAVIGATION_SEL_FONT_WEIGHT FW_MEDIUM//FW_SEMIBOLD
+
+#define NAVIGATION_SEL_TEXT_COLOR RGB(252, 252, 255)
+#define NAVIGATION_TEXT_COLOR RGB(222, 225, 234)
+#define NAVIGATION_BACK_COLOR RGB(137,145,156)//RGB(150,156,163)
+#define NAVIGATION_PADDING_LEFT 0
+#define NAVIGATION_PADDING_RIGHT 0
+
+#define PAGE_BACK_COLOR RGB(236, 234, 232)
+
+
+typedef struct _UI
+{
+ ULONG ref;
+ HBRUSH hbPage;
+ HBRUSH hbHeader;
+ HBRUSH hbNavItemSel;
+ HBRUSH hbNavBack;
+ HFONT hfHeader;
+ HFONT hfNavItem;
+ HFONT hfNavItemSel;
+ HFONT hfHeaderPageNum;
+ INT nHdrTxtHeight;
+ INT nHdrPageTxtHeight;
+ INT nNavTxtHeight;
+ INT nNavTxtSelHeight;
+ INT nHdrHeight;
+ INT nNavItemHeight;
+ COLORREF rgbPageBk;
+} UI;
+
+typedef struct _SPTHEME
+{
+ WNDPROC fnOldProc;
+ UI *pui;
+ BOOL bUnicode;
+} SPTHEME;
+
+static WASetup *g_pAttachInstance = NULL;
+static BOOL bUseMarquee = -1;
+
+static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static INT ConvertFontHeight(HWND hwnd, INT ptHeight);
+static DWORD GetHighestFontQuality(void);
+static BOOL InitializeUI(UI *pui, HWND hwndCtrl);
+static BOOL ReleaseUI(UI *pui);
+static const wchar_t *GetUnknownStr(void);
+static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static BOOL JobStatus_Advance(HWND hwndStatus);
+
+WASetup::WASetup(void)
+ : ref((size_t)1), hwnd(NULL), hwndActive(NULL), nPageActive((size_t)-1), pui(NULL), hWinamp(NULL)
+{
+}
+
+WASetup::~WASetup(void)
+{
+ if (hwnd && IsWindow(hwnd)) DestroyWindow(hwnd);
+ size_t index;
+ index = pageList.size();
+ while(index--)
+ {
+ pageList[index]->Release();
+ }
+
+ index = jobList.size();
+ while(index--)
+ {
+ jobList[index]->Release();
+ }
+}
+svc_setup *WASetup::CreateInstance()
+{
+ WASetup *instance = new WASetup();
+ return (svc_setup*)instance;
+}
+
+int WASetup::AddRef(void)
+{
+ return ++ref;
+}
+
+int WASetup::Release(void)
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+
+HRESULT WASetup::InsertPage(ifc_setuppage *pPage, int* pIndex)
+{
+ size_t index;
+ if (!pIndex || !pPage) return E_INVALIDARG;
+
+ index = *pIndex;
+ if (index >= pageList.size())
+ {
+ index = pageList.size();
+ pageList.push_back(pPage);
+ }
+ else
+ {
+ //pageList.insertBefore(*pIndex, pPage);
+ pageList.insert(pageList.begin() + index, pPage);
+ }
+
+ *pIndex = (int)index;
+ pPage->AddRef();
+ return S_OK;
+}
+
+HRESULT WASetup::RemovePage(size_t index)
+{
+ if (index >= pageList.size())
+ return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
+ pageList[index]->Release();
+ pageList.erase(pageList.begin() + index);
+ return S_OK;
+}
+
+HRESULT WASetup::GetPageCount(int *pCount)
+{
+ if (!pCount) return E_INVALIDARG;
+ *pCount = (int)pageList.size();
+ return S_OK;
+}
+
+HRESULT WASetup::GetPage(size_t index, ifc_setuppage **pPage)
+{
+ if (index >= pageList.size()) return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
+ *pPage = pageList[index];
+ return S_OK;
+}
+
+HRESULT WASetup::AddJob(ifc_setupjob *pJob)
+{
+ for (size_t i = 0; i < jobList.size(); i++)
+ {
+ if (jobList[i] == pJob) return S_OK;
+ }
+ jobList.push_back(pJob);
+ pJob->AddRef();
+ return S_OK;
+}
+
+HRESULT WASetup::RemoveJob(ifc_setupjob *pJob)
+{
+ for (size_t i = 0; i < jobList.size(); i++)
+ {
+ if (jobList[i] == pJob)
+ {
+ jobList[i]->Release();
+ jobList.erase(jobList.begin() + i);
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
+}
+
+HRESULT WASetup::GetActiveIndex(int* pIndex)
+{
+ if (!pIndex) return E_INVALIDARG;
+ *pIndex = (int)nPageActive;
+ return S_OK;
+}
+
+HRESULT WASetup::CreateStatusWnd(HWND *phwndStatus)
+{
+ HWND hwndStatus;
+
+ if (!phwndStatus) return S_FALSE;
+ *phwndStatus = NULL;
+
+ if (-1 == bUseMarquee)
+ {
+ OSVERSIONINFO vi;
+ vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ bUseMarquee = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0)));
+ }
+
+ hwndStatus = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUPSTATUS), NULL, JobStatusDialog);
+ if (!hwndStatus) return S_FALSE;
+
+ if (rcUI.right != rcUI.left)
+ {
+ RECT rw;
+ GetWindowRect(hwndStatus, &rw);
+ SetWindowPos(hwndStatus, NULL, rcUI.left + ((rcUI.right - rcUI.left) - (rw.right - rw.left))/2,
+ rcUI.top + ((rcUI.bottom - rcUI.top) - (rw.bottom - rw.top))/2, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS);
+ if (hwndCtrl)
+ {
+ if (bUseMarquee)
+ {
+ SetWindowLongPtrW(hwndCtrl, GWL_STYLE, GetWindowLongPtrW(hwndCtrl, GWL_STYLE) | 0x08/*PBS_MARQUEE*/);
+ SendMessageW(hwndCtrl, (WM_USER + 10)/*PBM_SETMARQUEE*/, TRUE, (LPARAM)200);
+ }
+ else
+ {
+ SendMessageW(hwndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 1 + (INT)(pageList.size() + jobList.size())));
+ SendMessageW(hwndCtrl, PBM_SETPOS, 0, 0L);
+ SendMessageW(hwndCtrl, PBM_SETSTEP, 1, 0L);
+ }
+ }
+
+ *phwndStatus = hwndStatus;
+ return S_OK;
+}
+
+static BOOL WaSetup_MessageLoop(HWND hMainWnd, HACCEL hAccel)
+{
+ MSG msg;
+
+ for (;;)
+ {
+ DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
+ if (WAIT_OBJECT_0 == status)
+ {
+ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ //if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
+ {
+ if (msg.message == WM_QUIT)
+ return (BOOL)msg.wParam;
+
+ if (!TranslateAcceleratorW(hMainWnd, hAccel, &msg) &&
+ !IsDialogMessageW(hMainWnd, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+ }
+ }
+ }
+}
+
+HRESULT WASetup::Start(HWND hwndWinamp)
+{
+ INT_PTR r(IDOK);
+
+ SetRectEmpty(&rcUI);
+
+ hWinamp = hwndWinamp;
+
+ if (pageList.size())
+ {
+ HACCEL hAccel;
+ static UI ui = {0, };
+
+ for (size_t i = 0; i < pageList.size(); i++) pageList[i]->Revert();
+ g_pAttachInstance = this;
+
+ InitializeUI(&ui, hwnd);
+ pui = &ui;
+
+ hwnd = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP), NULL, ::DialogProc);
+ if (!hwnd) return E_UNEXPECTED;
+ HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance;
+ hAccel = LoadAcceleratorsW(hInst, MAKEINTRESOURCEW(IDR_ACCEL_SETUP));
+
+ r = WaSetup_MessageLoop(hwnd, hAccel);
+
+ g_pAttachInstance = NULL;
+ ReleaseUI(&ui);
+ }
+
+ return (IDOK == r) ? S_OK : S_FALSE;
+}
+
+HRESULT WASetup::Save(HWND hwndStatus)
+{
+ HRESULT hr(S_OK);
+ HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS);
+ for (size_t i = 0; i < pageList.size(); i++)
+ {
+ if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_SAVING, NULL, 0));
+ if (S_OK != pageList[i]->Save(hwndText)) hr = S_FALSE;
+ JobStatus_Advance(hwndStatus);
+ }
+ WritePrivateProfileStringW(L"WinampReg", L"WAVer", AutoWide(APP_VERSION), INI_FILE);
+ return hr;
+}
+HRESULT WASetup::ExecJobs(HWND hwndStatus)
+{
+ HRESULT hr(S_OK);
+ HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS);
+ HWND hwndBtn = GetDlgItem(hwndStatus, IDC_BTN_SKIP);
+ for (size_t i = 0; i < jobList.size(); i++)
+ {
+ if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_JOBS, NULL, 0));
+ if (hwndBtn && S_OK == jobList[i]->IsCancelSupported() &&
+ SetPropW(hwndStatus, L"JOB", (HANDLE)jobList[i]))
+ {
+ EnableWindow(hwndBtn, TRUE);
+ }
+
+ if (S_OK != jobList[i]->Execute(hwndText)) hr = S_FALSE;
+ if (hwndBtn) EnableWindow(hwndBtn, FALSE);
+ JobStatus_Advance(hwndStatus);
+ }
+
+ return hr;
+}
+
+HRESULT WASetup::GetWinampWnd(HWND *phwndWinamp)
+{
+ if (NULL == phwndWinamp)
+ return E_INVALIDARG;
+ *phwndWinamp = hWinamp;
+ return (NULL == hWinamp) ? E_UNEXPECTED : S_OK;
+}
+
+static INT_PTR CALLBACK tmpProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+INT_PTR WASetup::OnInitDialog(HWND hwndFocused, LPARAM lParam)
+{
+ HWND hwndLB, hwndFrame, hwndHeader;
+ RECT rw, rc;
+ HICON hIcon = LoadIconW(hMainInstance, MAKEINTRESOURCE(ICON_XP));
+
+ // make other people's dialogs show the winamp icon
+ HWND h = CreateDialogW(hMainInstance, MAKEINTRESOURCE(IDD_OPENLOC), NULL, tmpProc);
+ SetClassLongPtrW(h, GCLP_HICON, (LONG_PTR)hIcon);
+ DestroyWindow(h);
+
+ SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDC_BTN_NEXT), TRUE);
+
+ wchar_t buf[256] = {0};
+ StringCchPrintfW(buf,256, getStringW(IDS_SETUP_WND_TITLE,NULL,0), AutoWideDup(app_version_string));
+ SetWindowTextW(hwnd, buf);
+
+ // adjust dialog
+ rw.left = GetPrivateProfileIntW(L"SETUP", L"left", 0, INI_FILE);
+ rw.top = GetPrivateProfileIntW(L"SETUP", L"top", 0, INI_FILE);
+ rw.right = GetPrivateProfileIntW(L"SETUP", L"right", 0, INI_FILE);
+ rw.bottom = GetPrivateProfileIntW(L"SETUP", L"bottom", 0, INI_FILE);
+
+ if (rw.left != rw.right && rw.top != rw.bottom)
+ {
+ INT x, y;
+ GetWindowRect(hwnd, &rc);
+ x = (rw.right) ? (rw.left + ((rw.right - rw.left) - (rc.right - rc.left))/2) : rw.left;
+ y = (rw.bottom) ? (rw.top + ((rw.bottom - rw.top) - (rc.bottom - rc.top))/2) : rw.top;
+ SetWindowPos(hwnd, NULL, x, y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ hwndFrame = GetDlgItem(hwnd, IDC_FRAME);
+
+ // TODO if this is needed again then remove
+ // deletes the 'Tools' menu as it's not used
+ DeleteMenu(GetMenu(hwnd), 2, MF_BYPOSITION);
+ DrawMenuBar(hwnd);
+
+ WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndFrame, GWLP_WNDPROC, (LONG_PTR)FrameWndProc);
+ if (fnOldProc) SetPropW(hwndFrame, L"SKINFRAME", fnOldProc);
+
+ SetWindowLongPtrW(hwndFrame, GWL_STYLE, GetWindowLongPtrW(hwndFrame, GWL_STYLE) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+ if (!IsWinXPTheme()) SetWindowLongPtrW(hwndFrame, GWL_EXSTYLE, (GetWindowLongPtrW(hwndFrame, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE) | WS_EX_STATICEDGE);
+ SetWindowPos(hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
+
+ GetClientRect(hwndFrame, &rc);
+ MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2);
+
+ hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION);
+ if (hwndLB)
+ {
+ GetWindowRect(hwndLB, &rw);
+ SetWindowPos(hwndLB, GetDlgItem(hwnd, IDC_BTN_BACK), rc.left, rc.top, rw.right - rw.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER);
+ SendMessageW(hwndLB, WM_SETFONT, (WPARAM)pui->hfNavItem, FALSE);
+ }
+
+ hwndHeader = GetDlgItem(hwnd, IDC_HEADER);
+ if (hwndHeader)
+ {
+ SendMessageW(hwndHeader, WM_SETFONT, (WPARAM)pui->hfHeader, FALSE);
+ GetWindowRect(hwndLB, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndHeader, NULL, rw.right, rc.top, rc.right - rw.right, pui->nHdrHeight, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
+ }
+
+ if (hwndLB)
+ {
+ for (size_t i = 0; i < pageList.size(); i++) SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)i);
+ SendMessageW(hwndLB, LB_SETCURSEL, 0, 0L);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB);
+ }
+
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ DWORD ourThreadID, foregroundThreadID;
+ foregroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
+ ourThreadID = GetCurrentThreadId();
+
+ if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, TRUE);
+ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, FALSE);
+
+ return 0;
+}
+
+void WASetup::OnDestroy(void)
+{
+ GetWindowRect(hwnd, &rcUI);
+}
+
+void WASetup::OnCancel(void)
+{
+ BOOL bNeedSave = FALSE;
+ WCHAR szTitle[128] = {0};
+
+ for (size_t i = 0; i < pageList.size() && !bNeedSave; i++)
+ {
+ bNeedSave = (S_FALSE != pageList[i]->IsDirty());
+ }
+
+ GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR));
+ if (bNeedSave)
+ {
+ INT nr = MessageBoxW(hwnd, getStringW(IDS_SAVE_CHANGES_BEFORE_EXIT, NULL, 0), szTitle, MB_YESNOCANCEL | MB_ICONWARNING);
+ switch(nr)
+ {
+ case IDYES: SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDM_FILE_SAVECHANGES, 0), 0L); break;
+ case IDCANCEL: return;
+ }
+ }
+ else if (IDNO == MessageBoxW(hwnd, getStringW(IDS_QUIT_OK, NULL, 0), szTitle, MB_YESNO | MB_ICONWARNING)) return;
+
+ DestroyWindow(hwnd);
+ PostQuitMessage(IDCANCEL);
+}
+
+void WASetup::OnNext_Clicked(HWND hwndCtrl)
+{
+ HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION);
+ INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) + 1;
+ if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB);
+}
+
+void WASetup::OnBack_Clicked(HWND hwndCtrl)
+{
+ HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION);
+ INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) -1;
+ if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB);
+}
+
+void WASetup::OnNavigation_SelChange(HWND hwndCtrl)
+{
+ HWND hwndFrame;
+ HMENU hMenu;
+ MENUITEMINFO mii;
+
+ INT idList[] = { IDC_BTN_BACK, IDC_BTN_NEXT};
+ INT count = (INT)SendMessageW(hwndCtrl, LB_GETCOUNT, 0, 0L);
+ INT index = (INT)SendMessageW(hwndCtrl, LB_GETCURSEL, 0, 0L);
+
+ if (nPageActive == (size_t)index) return;
+
+ if (-1 != nPageActive && S_FALSE == pageList[nPageActive]->Validate())
+ {
+ SendMessageW(hwndCtrl, LB_SETCURSEL, nPageActive, 0L);
+ return;
+ }
+
+ hwndFrame = GetDlgItem(hwnd, IDC_FRAME);
+ hMenu = GetMenu(hwnd);
+
+ mii.cbSize = sizeof(MENUITEMINFO);
+ mii.fMask = MIIM_STATE;
+
+ for(int i = sizeof(idList)/sizeof(int) - 1; i >= 0 ; i--)
+ {
+ HWND hwndBtn = GetDlgItem(hwnd, idList[i]);
+ BOOL bEnable = (IDC_BTN_NEXT == idList[i]) ? ((count - index) > 1) : (0 != index);
+ if (hwndBtn)
+ {
+ if (bEnable != IsWindowEnabled(hwndBtn))
+ {
+ if (IDC_BTN_NEXT == idList[i]) SendMessageW(hwnd, DM_SETDEFID, (WPARAM)((bEnable) ? IDC_BTN_NEXT : IDOK), 0L);
+ EnableWindow(hwndBtn, bEnable);
+ }
+
+ if (hMenu)
+ {
+ mii.fState = (bEnable) ? MFS_ENABLED : MFS_DISABLED;
+ SetMenuItemInfoW(hMenu, (IDC_BTN_NEXT == idList[i]) ? IDM_NAVIGATE_NEXT : IDM_NAVIGATE_BACK, FALSE, &mii);
+ }
+ }
+ }
+
+ if (hwndActive)
+ {
+ DestroyWindow(hwndActive);
+ hwndActive = NULL;
+ nPageActive = (size_t)-1;
+ }
+
+ if (S_OK != pageList[index]->CreateView(hwnd, &hwndActive))
+ hwndActive = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP_PAGE_ERROR), hwnd, ErrorPageDialog);
+
+ HWND hwndHeader;
+ RECT rc;
+ GetClientRect(hwndFrame, &rc);
+ MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2);
+
+ hwndHeader = GetDlgItem(hwnd, IDC_HEADER);
+ if (hwndHeader && (WS_VISIBLE & GetWindowLongPtrW(hwndHeader, GWL_STYLE)))
+ {
+ RECT rw;
+ GetWindowRect(hwndHeader, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ rc.top = rw.bottom;
+ rc.left = rw.left;
+ }
+
+ SetWindowPos(hwndActive, GetDlgItem(hwnd, IDC_LB_NAVIGATION), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE);
+
+ if(IsWinXPTheme()) WAEnableThemeDialogTexture(hwndActive, ETDT_ENABLETAB);
+ else
+ {
+ SPTHEME *pTheme = (SPTHEME*)malloc(sizeof(SPTHEME));
+ pTheme->bUnicode = IsWindowUnicode(hwndActive);
+ pTheme->pui = pui;
+ pTheme->fnOldProc = (WNDPROC)SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)PageWndProc);
+ if (!pTheme->fnOldProc || !SetPropW(hwndActive, L"SPTHEME", pTheme))
+ {
+ if (pTheme->fnOldProc) SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)pTheme->fnOldProc);
+ free(pTheme);
+ }
+ }
+ ShowWindow(hwndActive, SW_SHOW);
+ nPageActive = index;
+
+ if (hwndHeader) InvalidateRect(hwndHeader, NULL, FALSE);
+
+ HWND hwndTest = GetNextDlgTabItem(hwnd, GetWindow(hwndActive, GW_HWNDPREV), FALSE);
+ if (hwndTest) SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndTest, TRUE);
+}
+
+void WASetup::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDOK:
+ if (BN_CLICKED == nEvntID)
+ {
+ if (-1 != nPageActive && S_FALSE != pageList[nPageActive]->Validate())
+ {
+ DestroyWindow(hwnd);
+ PostQuitMessage(IDOK);
+ }
+ }
+ break;
+ case IDCANCEL: if (BN_CLICKED == nEvntID) OnCancel(); break;
+ case IDC_BTN_NEXT: if (BN_CLICKED == nEvntID) OnNext_Clicked(hwndCtrl); break;
+ case IDC_BTN_BACK: if (BN_CLICKED == nEvntID) OnBack_Clicked(hwndCtrl); break;
+
+ case IDC_LB_NAVIGATION:
+ switch(nEvntID)
+ {
+ case LBN_SELCHANGE: OnNavigation_SelChange(hwndCtrl); break;
+ }
+ break;
+
+ case IDM_HELP_ABOUT: WADialogBox(MAKEINTRESOURCEW(IDD_ABOUT), hwnd, AboutDialogProc); break;
+ case IDM_NAVIGATE_BACK: SendMessageW(GetDlgItem(hwnd, IDC_BTN_BACK), BM_CLICK, 0, 0L); break;
+ case IDM_NAVIGATE_NEXT: SendMessageW(GetDlgItem(hwnd, IDC_BTN_NEXT), BM_CLICK, 0, 0L); break;
+ case IDM_FILE_EXIT: OnCancel(); break;
+ case IDM_FILE_SAVECHANGES:
+ if (S_OK != Save(NULL))
+ {
+ WCHAR szTitle[128] = {0}, szText[256] = {0};
+ GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR));
+ MessageBoxW(hwnd, getStringW(IDS_CHANGES_NOT_SAVED, szText, sizeof(szText)/sizeof(wchar_t)), szTitle, MB_OK | MB_ICONERROR);
+ }
+ break;
+ }
+}
+
+void WASetup::OnDrawHeader(DRAWITEMSTRUCT *pdis)
+{
+ const wchar_t *pszName;
+ RECT ri, re;
+ INT top;
+
+ CopyRect(&ri, &pdis->rcItem);
+ CopyRect(&re, &ri);
+ re.right = ri.left + 1;
+
+ FillRect(pdis->hDC, &re, (HBRUSH)GetStockObject(WHITE_BRUSH));
+
+ ri.left = re.right;
+ SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL);
+ FillRect(pdis->hDC, &ri, pui->hbHeader);
+
+ if (nPageActive >= pageList.size() || S_OK != pageList[nPageActive]->GetName(FALSE, &pszName) || !*pszName) pszName = GetUnknownStr();
+
+ SetBkMode(pdis->hDC, TRANSPARENT);
+
+ InflateRect(&ri, -4, -2);
+
+ top = ri.top + (ri.bottom - ri.top - pui->nHdrTxtHeight)/2 - 1;
+ if (top > ri.top) ri.top = top;
+
+ if (ri.left < ri.right)
+ {
+ RECT rn;
+ wchar_t szPageInfo[64] = {0};
+ CopyRect(&rn, &ri);
+ SetTextColor(pdis->hDC, HEADER_PAGENUM_TEXT_COLOR);
+ UINT oldMode = SetTextAlign(pdis->hDC, TA_RIGHT);
+ HFONT hfOld = (pui->hfHeaderPageNum) ? (HFONT)SelectObject(pdis->hDC, pui->hfHeaderPageNum) : NULL;
+ top = ri.top + pui->nHdrTxtHeight - pui->nHdrPageTxtHeight;
+ if (top > rn.top) rn.top = top;
+ rn.right -= 8;
+ rn.left = rn.right - 42;
+ StringCchPrintfW(szPageInfo, sizeof(szPageInfo)/sizeof(wchar_t), L"%d/%d", nPageActive + 1, pageList.size());
+ ExtTextOutW(pdis->hDC, rn.right, rn.top, ETO_CLIPPED, &rn, szPageInfo, lstrlenW(szPageInfo), NULL);
+
+ SetTextAlign(pdis->hDC, oldMode);
+ if (hfOld) SelectObject(pdis->hDC, hfOld);
+ ri.right = rn.left -= 4;
+ }
+
+ if (ri.left < ri.right)
+ {
+ SetTextColor(pdis->hDC, HEADER_TEXT_COLOR);
+ SetTextAlign(pdis->hDC, TA_LEFT);
+ ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, pszName, lstrlenW(pszName), NULL);
+ }
+}
+
+void WASetup::OnDrawNavigationItem(DRAWITEMSTRUCT *pdis)
+{
+ const wchar_t *pszName;
+ RECT ri;
+ HFONT hfOld;
+ wchar_t szTitle[128] = {0};
+ COLORREF rgbText;
+
+ if (pdis->itemID == -1) return;
+
+ CopyRect(&ri, &pdis->rcItem);
+ ri.left += NAVIGATION_PADDING_LEFT;
+ ri.right -= NAVIGATION_PADDING_RIGHT;
+
+ if (ODA_FOCUS == pdis->itemAction)
+ {
+ if (0 == (0x0200/*ODS_NOFOCUSRECT*/ & pdis->itemState))
+ {
+ InflateRect(&ri, -1, -1);
+ DrawFocusRect(pdis->hDC, &ri);
+ }
+ return;
+ }
+
+ if (ODS_SELECTED & pdis->itemState)
+ {
+ HBRUSH hbActive;
+ if (pui->hbNavItemSel)
+ {
+ SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL);
+ hbActive = pui->hbNavItemSel;
+ }
+ else
+ {
+ SetBrushOrgEx(pdis->hDC, 0, 0, NULL);
+ hbActive = pui->hbNavBack;
+ }
+ FillRect(pdis->hDC, &ri, hbActive);
+ rgbText = SetTextColor(pdis->hDC, NAVIGATION_SEL_TEXT_COLOR);
+ hfOld = (HFONT)SelectObject(pdis->hDC, pui->hfNavItemSel);
+ }
+ else
+ {
+ if (ODA_SELECT == pdis->itemAction)
+ {
+ SetBrushOrgEx(pdis->hDC, 0, 0, NULL);
+ FillRect(pdis->hDC, &ri, pui->hbNavBack);
+ }
+ rgbText = 0;
+ hfOld = NULL;
+ }
+
+ if (pdis->itemData >= pageList.size() || S_OK != pageList[pdis->itemData]->GetName(TRUE, &pszName) || !*pszName)
+ pszName = GetUnknownStr();
+
+ SetBkMode(pdis->hDC, TRANSPARENT);
+
+ InflateRect(&ri, -4, -2);
+ INT top = ri.top + (ri.bottom - ri.top - pui->nNavTxtHeight)/2 - 1;
+ if (top > ri.top) ri.top = top;
+
+ StringCchPrintfW(szTitle, sizeof(szTitle)/sizeof(wchar_t), L"%d. %s", pdis->itemData + 1, pszName);
+ ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, szTitle, lstrlenW(szTitle), NULL);
+
+ if (ODS_SELECTED & pdis->itemState)
+ {
+ SetTextColor(pdis->hDC, rgbText);
+ if (hfOld) SelectObject(pdis->hDC, hfOld);
+ }
+}
+
+INT_PTR WASetup::OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_HEADER: OnDrawHeader(pdis); return TRUE;
+ case IDC_LB_NAVIGATION: OnDrawNavigationItem(pdis); return TRUE;
+ }
+ return 0;
+}
+
+INT_PTR WASetup::OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_NAVIGATION:
+ pmis->itemHeight = (pui) ? pui->nNavItemHeight : 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+INT_PTR WASetup::OnColorListBox(HDC hdc, HWND hwndCtrl)
+{
+ if (hwndCtrl == GetDlgItem(hwnd, IDC_LB_NAVIGATION))
+ {
+
+ SetTextColor(hdc, NAVIGATION_TEXT_COLOR);
+ SetBkColor(hdc, NAVIGATION_BACK_COLOR);
+ return (INT_PTR)pui->hbNavBack;
+ }
+ return NULL;
+}
+
+INT_PTR WASetup::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ INT_PTR result = 0;
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: OnDestroy(); break;
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ case WM_DRAWITEM: result = OnDrawItem((INT)wParam, (DRAWITEMSTRUCT*)lParam); break;
+ case WM_MEASUREITEM: result = OnMeasureItem((INT)wParam, (MEASUREITEMSTRUCT*)lParam); break;
+ case WM_CTLCOLORLISTBOX: return OnColorListBox((HDC)wParam, (HWND)lParam);
+ case WM_CHAR:
+ if (0x30 == wParam)
+ {
+ OutputDebugStringA("test\n");
+ return 0;
+ }
+ }
+
+ if (result)
+ {
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONG_PTR)result);
+ return TRUE;
+ }
+
+ return 0;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WASetup *pInst = (WASetup*)GetPropW(hwndDlg, L"SETUPDLG");
+ if (!pInst && g_pAttachInstance)
+ {
+ pInst = g_pAttachInstance;
+ pInst->hwnd = hwndDlg;
+ SetPropW(hwndDlg, L"SETUPDLG", pInst);
+ g_pAttachInstance = NULL;
+ }
+
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->DialogProc(uMsg, wParam, lParam);
+ RemovePropW(hwndDlg, L"SETUPDLG");
+ pInst = NULL;
+ }
+ break;
+ }
+
+ return (pInst) ? pInst->DialogProc(uMsg, wParam, lParam) : 0;
+}
+
+static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_SETIMAGE, IMAGE_BITMAP,
+ (LPARAM)WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_ABOUT), FALSE));
+
+ wchar_t buf[2048] = {0}, buf2[2048] = {0};
+ GetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf,ARRAYSIZE(buf));
+ StringCchPrintfW(buf2,2048,(buf[0] ? buf : L"v%s %s - %s"),AutoWideDup(app_version_string),AutoWideDup(APP_VERSION_PLATFORM),AutoWideDup(app_date));
+ SetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf2);
+ }
+ break;
+ case WM_DESTROY:
+ {
+ DeleteObject((HBITMAP)SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_GETIMAGE, IMAGE_BITMAP, 0L));
+ }
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_BTN_SKIP:
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ ifc_setupjob *pj = (ifc_setupjob*)GetPropW(hwndDlg, L"JOB");
+ if (pj)
+ {
+ HWND hwndStatus = GetDlgItem(hwndDlg, IDC_LBL_STATUS);
+ EnableWindow((HWND)lParam, FALSE);
+ if (hwndStatus) SetWindowTextW(hwndStatus, getStringW(IDS_HTTP_ABORT, NULL, 0));
+ pj->Cancel(hwndStatus);
+ }
+ }
+ break;
+ }
+ case WM_DESTROY:
+ RemovePropW(hwndDlg, L"JOB");
+ }
+
+ return 0;
+}
+
+static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_WINDOWPOSCHANGED:
+ if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & ((WINDOWPOS*)lParam)->flags))
+ {
+ HWND messageWindow;
+ messageWindow = GetDlgItem(hwndDlg, IDC_LBL_MESSAGE);
+ if (NULL != messageWindow)
+ {
+ RECT rect;
+ long top;
+
+ GetWindowRect(messageWindow, &rect);
+ MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT*)&rect, 1);
+
+ top = rect.top;
+
+ GetClientRect(hwndDlg, &rect);
+ rect.top = top;
+
+ SetWindowPos(messageWindow, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ SPTHEME *pTheme = (SPTHEME*)GetPropW(hwnd, L"SPTHEME");
+ if (!pTheme || !pTheme->fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+
+ switch(uMsg)
+ {
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORSTATIC:
+ SetBkColor((HDC)wParam, PAGE_BACK_COLOR);
+ SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT));
+ return (LRESULT)pTheme->pui->hbPage;
+ case WM_DESTROY:
+ {
+ WNDPROC fnOldProc = pTheme->fnOldProc;
+ RemovePropA(hwnd, "SPTHEME");
+ free(pTheme);
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc);
+ return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam);
+ }
+ }
+
+ return (pTheme->bUnicode) ? CallWindowProcW(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam) :
+ CallWindowProcA(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam);
+}
+
+static DWORD GetHighestFontQuality(void)
+{
+ DWORD fdwQuality;
+ BOOL bSmoothing;
+
+ if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &bSmoothing, 0) && bSmoothing)
+ {
+ OSVERSIONINFO vi = { sizeof(OSVERSIONINFO), };
+ fdwQuality = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0))) ?
+ 5/*CLEARTYPE_QUALITY*/ : ANTIALIASED_QUALITY;
+ }
+ else fdwQuality = DEFAULT_QUALITY;
+
+ return fdwQuality;
+}
+
+static BOOL InitializeUI(UI *pui, HWND hwndCtrl)
+{
+ if (!pui) return FALSE;
+ if (!pui->ref)
+ {
+ HBITMAP hbmp;
+ BITMAP bi;
+ HDC hdc;
+ INT logPx;
+ TEXTMETRIC tm;
+
+ hdc = GetWindowDC(hwndCtrl);
+ logPx = GetDeviceCaps(hdc, LOGPIXELSY);
+
+ pui->hbPage = CreateSolidBrush(PAGE_BACK_COLOR);
+
+ hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVIGATION_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+ if (hbmp)
+ {
+ pui->hbNavBack = CreatePatternBrush(hbmp);
+ DeleteObject(hbmp);
+ }
+ else pui->hbNavBack = CreateSolidBrush(NAVIGATION_BACK_COLOR);
+
+ pui->hfNavItem = CreateFontA(-MulDiv(NAVIGATION_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_FONT_WEIGHT,
+ NAVIGATION_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_FONT_NAME);
+
+ pui->hfNavItemSel = CreateFontA(-MulDiv(NAVIGATION_SEL_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_SEL_FONT_WEIGHT,
+ NAVIGATION_SEL_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_SEL_FONT_NAME);
+
+ pui->hfHeader = CreateFontA(-MulDiv(HEADER_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_FONT_WEIGHT,
+ HEADER_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ GetHighestFontQuality(), FF_DONTCARE, HEADER_FONT_NAME);
+
+ pui->hfHeaderPageNum = CreateFontA(-MulDiv(HEADER_PAGENUM_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_PAGENUM_FONT_WEIGHT,
+ HEADER_PAGENUM_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ GetHighestFontQuality(), FF_DONTCARE, HEADER_PAGENUM_FONT_NAME);
+
+ pui->nHdrHeight = 36;
+
+ hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_HEADER_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+ if (hbmp)
+ {
+ if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nHdrHeight = bi.bmHeight;
+ pui->hbHeader = CreatePatternBrush(hbmp);
+ DeleteObject(hbmp);
+ }
+
+ pui->nNavItemHeight = 32;
+// hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVITEM_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+// if (hbmp)
+// {
+// if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nNavItemHeight = bi.bmHeight;
+// pui->hbNavItemSel = CreatePatternBrush(hbmp);
+// DeleteObject(hbmp);
+// }
+
+ HFONT hfOld = (HFONT)SelectObject(hdc, pui->hfHeader);
+ GetTextMetrics(hdc, &tm);
+ pui->nHdrTxtHeight = tm.tmAscent;
+
+ SelectObject(hdc, pui->hfHeaderPageNum);
+ GetTextMetrics(hdc, &tm);
+ pui->nHdrPageTxtHeight = tm.tmAscent;
+
+ SelectObject(hdc, pui->hfNavItem);
+ GetTextMetrics(hdc, &tm);
+ pui->nNavTxtHeight = tm.tmAscent;
+
+ SelectObject(hdc, pui->hfNavItemSel);
+ GetTextMetrics(hdc, &tm);
+ pui->nNavTxtSelHeight = tm.tmAscent;
+
+ SelectObject(hdc, hfOld);
+ ReleaseDC(hwndCtrl, hdc);
+ }
+ pui->ref++;
+ return TRUE;
+}
+
+static BOOL ReleaseUI(UI *pui)
+{
+ if (!pui) return FALSE;
+ if (0 == pui->ref)
+ {
+ return TRUE;
+ }
+ if (1 == pui->ref)
+ {
+ if (pui->hbPage) DeleteObject(pui->hbPage);
+ if (pui->hbNavBack) DeleteObject(pui->hbNavBack);
+ if (pui->hbHeader) DeleteObject(pui->hbHeader);
+ if (pui->hbNavItemSel) DeleteObject(pui->hbNavItemSel);
+ if (pui->hfNavItem) DeleteObject(pui->hfNavItem);
+ if (pui->hfNavItemSel) DeleteObject(pui->hfNavItemSel);
+ if (pui->hfHeader) DeleteObject(pui->hfHeader);
+ if (pui->hfHeaderPageNum) DeleteObject(pui->hfHeaderPageNum);
+ ZeroMemory(pui, sizeof(UI));
+ return TRUE;
+ }
+ pui->ref--;
+ return TRUE;
+}
+
+static const wchar_t *GetUnknownStr(void)
+{
+ static wchar_t unknown[64] = {0,};
+ return (unknown) ? unknown : getStringW(IDS_UNKNOWN, unknown, sizeof(unknown)/sizeof(wchar_t));
+}
+
+static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"SKINFRAME");
+ if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ RemovePropW(hwnd, L"SKINFRAME");
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc);
+ break;
+ case WM_PAINT:
+ ValidateRect(hwnd, NULL);
+ return 0;
+ case WM_ERASEBKGND: return 1;
+ }
+ return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam);
+}
+
+static BOOL JobStatus_Advance(HWND hwndStatus)
+{
+ if (bUseMarquee > 0 ) return TRUE;
+ if (!hwndStatus) return FALSE;
+ HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS);
+ if (!hwndCtrl) return FALSE;
+ SendMessageW(hwndCtrl, PBM_STEPIT, 0, 0L);
+ return TRUE;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS WASetup
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUP_INSERT_PAGE, InsertPage)
+CB(API_SETUP_REMOVE_PAGE, RemovePage)
+CB(API_SETUP_GET_PAGE_COUNT, GetPageCount)
+CB(API_SETUP_GET_PAGE, GetPage)
+CB(API_SETUP_GET_ACTIVE_INDEX, GetActiveIndex)
+CB(API_SETUP_START, Start)
+CB(API_SETUP_ADD_JOB, AddJob)
+CB(API_SETUP_REMOVE_JOB, RemoveJob)
+CB(API_SETUP_CREATE_STATUSWND, CreateStatusWnd)
+CB(API_SETUP_SAVE, Save)
+CB(API_SETUP_EXECJOBS, ExecJobs)
+CB(API_SETUP_GETWINAMPWND, GetWinampWnd)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/setup.h b/Src/Winamp/setup/setup.h
new file mode 100644
index 00000000..8344bad7
--- /dev/null
+++ b/Src/Winamp/setup/setup.h
@@ -0,0 +1,66 @@
+#ifndef NULLSOFT_WINAMP_SETUP_HEADER
+#define NULLSOFT_WINAMP_SETUP_HEADER
+
+#include "./svc_setup.h"
+#include <vector>
+
+typedef struct _UI UI;
+
+class WASetup : svc_setup
+{
+protected:
+ WASetup(void);
+ ~WASetup(void);
+public:
+ static svc_setup *CreateInstance();
+public:
+ int AddRef(void);
+ int Release(void);
+ HRESULT InsertPage(ifc_setuppage *pPage, int*pIndex);
+ HRESULT RemovePage(size_t index);
+ HRESULT GetPageCount(int*pCount);
+ HRESULT GetPage(size_t index, ifc_setuppage **pPage);
+ HRESULT AddJob(ifc_setupjob *pJob);
+ HRESULT RemoveJob(ifc_setupjob *pJob);
+ HRESULT GetActiveIndex(int*pIndex);
+ HRESULT Start(HWND hwndWinamp);
+ HRESULT CreateStatusWnd(HWND *phwndStatus);
+ HRESULT Save(HWND hwndStatus);
+ HRESULT ExecJobs(HWND hwndStatus);
+ HRESULT GetWinampWnd(HWND *phwndWinamp);
+
+protected:
+ INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocused, LPARAM lParam);
+ void OnDestroy(void);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+ void OnCancel(void); // use it if you want prompt user first
+ void OnCancel_Clicked(void);
+ void OnNext_Clicked(HWND hwndCtrl);
+ void OnBack_Clicked(HWND hwndCtrl);
+ void OnNavigation_SelChange(HWND hwndCtrl);
+ INT_PTR OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis);
+ INT_PTR OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis);
+ void OnDrawHeader(DRAWITEMSTRUCT *pdis);
+ void OnDrawNavigationItem(DRAWITEMSTRUCT *pdis);
+ INT_PTR OnColorListBox(HDC hdc, HWND hwndCtrl);
+
+private:
+ int ref;
+ HWND hwnd;
+ std::vector<ifc_setuppage*> pageList;
+ std::vector<ifc_setupjob*> jobList;
+ HWND hwndActive;
+ size_t nPageActive;
+ UI *pui;
+ RECT rcUI;
+ HWND hWinamp;
+
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+
+};
+
+
+#endif //WINAMP_SETUP_WIZARD_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/setup.rc b/Src/Winamp/setup/setup.rc
new file mode 100644
index 00000000..503c2811
--- /dev/null
+++ b/Src/Winamp/setup/setup.rc
@@ -0,0 +1,446 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "setup_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "setup_resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SETUP DIALOGEX 0, 0, 369, 214
+STYLE DS_SETFONT | DS_NOIDLEMSG | DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
+CAPTION "Winamp Setup"
+MENU IDR_SETUPMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LISTBOX IDC_FRAME,7,6,355,180,NOT LBS_NOTIFY | LBS_NOREDRAW | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_NODATA | LBS_NOSEL | WS_DISABLED
+ LISTBOX IDC_LB_NAVIGATION,7,6,96,180,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_DISABLED | NOT WS_BORDER | WS_TABSTOP
+ PUSHBUTTON "&Cancel",IDCANCEL,7,194,50,14
+ PUSHBUTTON "&Back",IDC_BTN_BACK,197,194,50,14
+ DEFPUSHBUTTON "&Next",IDC_BTN_NEXT,255,194,50,14
+ PUSHBUTTON "Fini&sh",IDOK,312,194,50,14
+ CONTROL "",IDC_HEADER,"Static",SS_OWNERDRAW,129,8,233,28
+END
+
+IDD_SETUP_PAGE_ASSOC DIALOGEX 0, 0, 241, 152
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Select the file types you want to be associated with Winamp.",IDC_LBL_HEADER,6,6,229,18
+ CONTROL "",IDC_TREE_TYPES,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,6,24,229,87
+ CONTROL "Show Winamp in the folder context menus in Windows Explorer",IDC_CHK_EXPLORER_MENU,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,115,229,10
+ CONTROL "Enable Winamp Agent",IDC_CHK_AGENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,126,229,9
+ LTEXT "Places a Winamp icon in the notification area.",IDC_LBL_AGENT_DESC,17,136,218,9
+END
+
+#if defined(APSTUDIO_INVOKED) || defined(NOT_USED)
+#if defined(APSTUDIO_INVOKED)
+IDD_SETUP_PAGE_CONNECT$(NOT_USED) DIALOGEX 0, 0, 225, 137
+#else
+IDD_SETUP_PAGE_CONNECT DIALOGEX 0, 0, 225, 137
+#endif
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Select your internet connection type:",IDC_LBL_HEADER,6,6,213,18
+ COMBOBOX IDC_CB_CONNECT,6,24,213,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "HTTP Proxy (Optional)",IDC_GRP_PROXY,6,49,213,82
+ EDITTEXT IDC_EDT_SERVER,16,82,193,14,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "Server address (Server:Port):",IDC_LBL_SERVER,16,71,193,8
+ CONTROL "Use proxy only for port 80 URLs",IDC_CHK_PORT80,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,101,193,10
+END
+#endif
+
+IDD_SETUP_PAGE_SKIN DIALOGEX 0, 0, 257, 158
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
+EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Choose the look and feel for your Winamp.",IDC_LBL_HEADER,5,6,246,8
+ LISTBOX IDC_LB_SKIN,5,24,101,126,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Preview",IDC_GRP_PREVIEW,114,22,137,128
+ CONTROL "",IDC_PIC_PREVIEW,"Static",SS_BITMAP,122,35,124,43
+ LTEXT "Name:",IDC_LBL_NAME,122,87,28,8
+ EDITTEXT IDC_EDT_NAME,150,87,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_TRANSPARENT
+ LTEXT "Type:",IDC_LBL_TYPE,122,98,20,8
+ EDITTEXT IDC_EDT_TYPE,150,98,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Author:",IDC_LBL_AUTHOR,122,109,26,8
+ EDITTEXT IDC_EDT_AUTHOR,150,109,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Version:",IDC_LBL_VERSION,122,120,27,8
+ EDITTEXT IDC_EDT_VERSION,150,120,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ PUSHBUTTON "More Info...",IDC_BTN_MOREINFO,194,133,52,13,NOT WS_VISIBLE
+END
+
+IDD_ABOUT DIALOGEX 0, 0, 206, 54
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Winamp Setup - About"
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
+BEGIN
+ CONTROL 108,IDC_PIC_ABOUT,"Static",SS_BITMAP | SS_REALSIZEIMAGE,4,4,35,32,WS_EX_TRANSPARENT
+ LTEXT "Winamp Setup Wizard",IDC_STATIC,50,4,152,8
+ LTEXT "Copyright © 1997-2023 Winamp SA",IDC_STATIC,50,15,152,9,NOT WS_GROUP
+ LTEXT "v%s %s - %s",IDC_VER_TEXT,4,42,144,8
+ DEFPUSHBUTTON "Close",IDOK,152,36,50,14
+END
+
+#if defined(APSTUDIO_INVOKED) || defined(NOT_USED)
+#if defined(APSTUDIO_INVOKED)
+IDD_SETUP_PAGE_LANG$(NOT_USED) DIALOGEX 0, 0, 160, 152
+#else
+IDD_SETUP_PAGE_LANG DIALOGEX 0, 0, 160, 152
+#endif
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Choose one of the available languages:",IDC_LBL_HEADER,6,6,148,18
+ LISTBOX IDC_LB_LANG,6,24,148,122,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+END
+#endif
+
+#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
+#if defined(APSTUDIO_INVOKED)
+IDD_SETUP_PAGE_FEEDBACK$(DISABLED) DIALOGEX 0, 0, 256, 158
+#else
+IDD_SETUP_PAGE_FEEDBACK DIALOGEX 0, 0, 256, 158
+#endif
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Let us know more about you so we can continue to improve Winamp.",IDC_LBL_HEADER,5,6,245,18
+ LTEXT "Email:",IDC_LBL_EMAIL,12,36,102,12
+ EDITTEXT IDC_EDT_EMAIL,114,36,130,12,ES_AUTOHSCROLL
+ LTEXT "Zip code (US) or Country:",IDC_LBL_COUNTRY,12,51,98,12
+ EDITTEXT IDC_EDT_COUNTRY,114,51,130,12,ES_AUTOHSCROLL
+ LTEXT "Gender:",IDC_LBL_GENDER,12,67,98,12
+ COMBOBOX IDC_CB_GENDER,114,66,130,46,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Yes, send me information about Winamp",IDC_CHK_ANNOUNCEMENTS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,129,232,10
+ CONTROL "Yes, allow anonymous usage statistics (recommended)",IDC_CHK_STATISTICS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,140,232,10
+END
+#endif
+
+IDD_SETUPSTATUS DIALOGEX 0, 0, 249, 71
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "Winamp Setup"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_LBL_STATUS,"Static",SS_LEFTNOWORDWRAP | SS_ENDELLIPSIS | WS_GROUP,11,12,226,9
+ CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,11,25,226,12
+ PUSHBUTTON "Skip",IDC_BTN_SKIP,181,47,56,14,WS_DISABLED
+END
+
+IDD_SETUP_PAGE_ERROR DIALOGEX 0, 0, 316, 183
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Unable to load setup page",IDC_LBL_MESSAGE,5,37,304,8
+END
+
+IDD_SETUP_PAGE_ASSOC_WIN8 DIALOGEX 0, 0, 257, 152
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Select the file types you want to be associated with Winamp.",IDC_LBL_HEADER,5,6,248,18
+ LTEXT "To associate files with Winamp on this version of Windows, you need to go to 'Set Default Programs' in the Control Panel once Winamp's setup is complete.\n\nNote: This can also be accessed via Winamp's 'File Types' preferences page.",IDC_STATIC,5,24,248,32
+ CONTROL "Launch Winamp for Audio CDs",IDC_CHK_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,66,242,9
+ CONTROL "Show Winamp in the folder context menus in Windows Explorer",IDC_CHK_EXPLORER_MENU,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,78,242,10
+ CONTROL "Enable Winamp Agent",IDC_CHK_AGENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,90,242,9
+ LTEXT "Places a Winamp icon in the notification area.",IDC_LBL_AGENT_DESC,22,101,231,9
+ CONTROL "",IDC_TREE_TYPES,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | NOT WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_TABSTOP,5,144,248,0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_SETUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 362
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 208
+ HORZGUIDE, 186
+ END
+
+ IDD_SETUP_PAGE_ASSOC, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 235
+ VERTGUIDE, 17
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 144
+ HORZGUIDE, 24
+ END
+
+ "IDD_SETUP_PAGE_CONNECT$(NOT_USED)", DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 219
+ VERTGUIDE, 16
+ VERTGUIDE, 209
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 131
+ HORZGUIDE, 24
+ HORZGUIDE, 49
+ HORZGUIDE, 111
+ END
+
+ IDD_SETUP_PAGE_SKIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 251
+ VERTGUIDE, 106
+ VERTGUIDE, 114
+ VERTGUIDE, 122
+ VERTGUIDE, 150
+ VERTGUIDE, 246
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 150
+ HORZGUIDE, 24
+ HORZGUIDE, 35
+ END
+
+ IDD_ABOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 202
+ VERTGUIDE, 50
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 50
+ END
+
+ "IDD_SETUP_PAGE_LANG$(NOT_USED)", DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 154
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 146
+ HORZGUIDE, 24
+ END
+
+ IDD_SETUPSTATUS, DIALOG
+ BEGIN
+ LEFTMARGIN, 11
+ RIGHTMARGIN, 237
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 61
+ END
+
+ IDD_SETUP_PAGE_ERROR, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 309
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 176
+ END
+
+ IDD_SETUP_PAGE_ASSOC_WIN8, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 253
+ VERTGUIDE, 11
+ TOPMARGIN, 6
+ BOTTOMMARGIN, 144
+ HORZGUIDE, 24
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_SETUPMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Save Changes\tCtrl+S", 40013
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit\tAlt+F4", 40016
+ END
+ POPUP "Na&vigation"
+ BEGIN
+ MENUITEM "&Back\tAlt+B", 40011
+ MENUITEM "&Next\tAlt+N", 40012
+ END
+ POPUP "&Tools", GRAYED
+ BEGIN
+ MENUITEM "Migrate/Import...", 40009
+ MENUITEM "Register Winamp...", 40010
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About\tF1", 40008
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_HEADER_STRIP BITMAP "headerstrip.bmp"
+IDB_NAVITEM_STRIP BITMAP "navitemstrip.bmp"
+IDB_CHECKBOX BITMAP "checkbox.bmp"
+IDB_NAVIGATION_STRIP BITMAP "navstrip.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// PNG
+//
+
+IDB_PREVIEW_NO PNG "preview_no.png"
+IDB_PREVIEW_CLASSIC PNG "preview_classic.png"
+IDB_ABOUT PNG "smokingllama.png"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCEL_SETUP ACCELERATORS
+BEGIN
+ VK_F1, IDM_HELP_ABOUT, VIRTKEY, NOINVERT
+ "S", IDM_FILE_SAVECHANGES, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_SKIN_CURRENT "Current"
+ IDS_SKIN_PROMO1 "Bento Skin"
+ IDS_SKIN_PROMO2 "Bento Skin (Large)"
+ IDS_PAGE_SKIN "Skin"
+ IDS_PAGE_LANGUAGE "Language"
+ IDS_PAGE_CONNECTIVITY "Connectivity"
+ IDS_SAVE_CHANGES_BEFORE_EXIT "Do you want to save changes before exit?"
+ IDS_UNKNOWN "Unknown"
+ IDS_CHANGES_NOT_SAVED "Some settings were not saved."
+ IDS_MODERN "Modern"
+ IDS_CLASSIC "Classic"
+ IDS_QUIT_OK "Are you sure you want to quit Winamp Setup?"
+ IDS_PAGE_ASSOCIATIONS "Associations"
+ IDS_FILETYPE_VIDEO "Video Files"
+ IDS_FILETYPE_AUDIO "Audio Files"
+ IDS_FILETYPE_UNKNOWN "Other Files"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_FILETYPE_PLAYLIST "Playlist Files"
+ IDS_PAGE_FEEDBACK "Feedback"
+ IDS_GENDER_MALE "Male"
+ IDS_GENDER_FEMALE "Female"
+ IDS_GENDER_UNKNOWN "Select gender"
+ IDS_REGISTER_CDPLAYER "Launch Winamp for Audio CDs"
+ IDS_STATUS_SAVING "Saving settings"
+ IDS_STATUS_JOBS "Executing scripts"
+ IDS_STATUS_RUNWA "Starting Winamp"
+ IDS_PAGE_SKIN_LONG "Choose Skin"
+ IDS_REGISTER_AGENT "Enable Winamp Agent"
+ IDS_PAGE_ASSOCIATIONS_LONG "File Associations"
+ IDS_PAGE_FEEDBACK_LONG "User Feedback"
+ IDS_PAGE_INCORRECT_EMAIL_ADDRESS "Incorrect email address."
+ IDS_FILETYPE_AUXILIARY "Winamp Specific Files"
+ IDS_WINAMP_SKIN_MODERN "Winamp Skin (Modern)"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_WINAMP_SKIN_CLASSIC "Winamp Skin (Classic)"
+ IDS_WINAMP_LANG_PACK "Winamp Language Pack"
+ IDS_DOWNLOADSTATUS_INITIALIZING "Initializing..."
+ IDS_DOWNLOADSTATUS_CONNECTING "Connecting..."
+ IDS_DOWNLOADSTATUS_CONNECTED "Connected"
+ IDS_DOWNLOADSTATUS_RECEIVING "Downloading..."
+ IDS_DOWNLOADSTATUS_RECEIVINGPERCENT "Downloading... (%d%% completed)"
+ IDS_DOWNLOADSTATUS_SUCCESS "Success."
+ IDS_DOWNLOADSTATUS_FAILED "Failed."
+ IDS_DOWNLOADSTATUS_ABORTING "Aborting..."
+ IDS_DOWNLOADSTATUS_ABORTED "Aborted."
+ IDS_SETUP_WND_TITLE "Winamp v%s Setup"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Winamp/setup/setup_api.h b/Src/Winamp/setup/setup_api.h
new file mode 100644
index 00000000..8ed8c1b6
--- /dev/null
+++ b/Src/Winamp/setup/setup_api.h
@@ -0,0 +1,24 @@
+#ifndef WINAMP_SETUP_API_HEADER
+#define WINAMP_SETUP_API_HEADER
+
+#include <windows.h>
+
+
+class __declspec(novtable) WASetupAPI
+{
+protected:
+ WASetupAPI(void){};
+ virtual ~WASetupAPI(void) = 0;
+public:
+ virtual INT GetInterfaceVersion(void) = 0;
+ virtual LPCWSTR GetName(BOOL bShort) = 0;
+ virtual HICON GetIcon(BOOL bSmall) = 0;
+ virtual BOOL Initialize(void) = 0;
+ virtual BOOL Finish(BOOL bCancelled) = 0;
+ virtual HWND CreateView(HWND hwndParent) = 0;
+ virtual HWND GetHWND(void) = 0;
+};
+
+
+
+#endif //WINAMP_SETUP_API_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/setup_resource.h b/Src/Winamp/setup/setup_resource.h
new file mode 100644
index 00000000..6e44de7a
--- /dev/null
+++ b/Src/Winamp/setup/setup_resource.h
@@ -0,0 +1,139 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by setup.rc
+//
+#define IDD_SETUP 101
+#define IDB_CHECKBOX 101
+#define IDD_SETUP_PAGE_LANG1 102
+#define IDD_SETUP_PAGE_ASSOC 102
+#define IDD_SETUP_PAGE_CONNECT 103
+#define IDD_SETUP_PAGE_SKIN 104
+#define IDD_ABOUT 105
+#define IDB_HEADERSTRIP 106
+#define IDB_HEADER_STRIP 106
+#define IDD_SETUP_PAGE_LANG 106
+#define IDD_SETUP_PAGE_FEEDBACK 107
+#define IDB_ABOUT 108
+#define IDD_SETUP_PAGE_ERROR 108
+#define IDD_SETUPSTATUS 109
+#define IDB_NAVIGATION_STRIP 110
+#define IDB_NAVITEM_STRIP 111
+#define IDB_PREVIEW_CLASSIC 112
+#define IDR_ACCEL_SETUP 112
+#define IDB_PREVIEW_NO 113
+#define IDD_SETUP_PAGE_ASSOC_WIN8 114
+#define IDR_SETUPMENU 191
+#define IDC_CB_CONNECT 1000
+#define IDC_LBL_MESSAGE 1000
+#define IDC_BTN_NEXT 1001
+#define IDC_EDT_SERVER 1001
+#define IDC_VER_TEXT 1001
+#define IDC_BTN_BACK 1002
+#define IDC_CHK_PORT80 1002
+#define IDC_LB_NAVIGATION 1003
+#define IDC_EDT_EMAIL 1003
+#define IDC_FRAME 1004
+#define IDC_GRP_PROXY 1004
+#define IDC_CHK_ANNOUNCEMENTS 1004
+#define IDC_EDT_TEST 1005
+#define IDC_LBL_SERVER 1005
+#define IDC_BTN_TEST_ME 1006
+#define IDC_TREE_TYPES 1006
+#define IDC_LBL_COUNTRY 1006
+#define IDC_HEADER 1007
+#define IDC_LBL_HEADER 1007
+#define IDC_LBL_GENDER 1008
+#define IDC_LBL_EMAIL 1011
+#define IDC_EDT_COUNTRY 1012
+#define IDC_CHK_STATISTICS 1013
+#define IDC_CHK_FEEDBACK 1014
+#define IDC_GRP_FEEDBACK 1015
+#define IDC_LB_LANG 1016
+#define IDC_CB_GENDER 1016
+#define IDC_LB_SKIN 1017
+#define IDC_LBL_STATUS 1017
+#define IDC_EDT_INFO 1018
+#define IDC_PROGRESS 1018
+#define IDC_PIC_PREVIEW 1020
+#define IDC_LBL_CAPTION 1021
+#define IDC_CHK_AGENT 1021
+#define IDC_EDT_NAME 1022
+#define IDC_LBL_AGENT_DESC 1022
+#define IDC_EDT_TYPE 1023
+#define IDC_CHK_EXPLORER_MENU 1023
+#define IDC_LBL_NAME 1024
+#define IDC_BTN_SKIP 1024
+#define IDC_LBL_TYPE 1025
+#define IDC_GRP_PREVIEW 1026
+#define IDC_LBL_VERSION 1027
+#define IDC_EDT_VERSION 1028
+#define IDC_LBL_TYPE3 1029
+#define IDC_LBL_AUTHOR 1029
+#define IDC_EDT_AUTHOR 1030
+#define IDC_PIC_ABOUT 1032
+#define IDC_BTN_MOREINFO 1033
+#define IDC_CHK_CD 1034
+#define IDS_SKIN_CURRENT 2000
+#define IDS_SKIN_PROMO1 2001
+#define IDS_SKIN_PROMO2 2002
+#define IDS_PAGE_SKIN 2003
+#define IDS_PAGE_LANGUAGE 2004
+#define IDS_PAGE_CONNECTIVITY 2005
+#define IDS_SAVE_CHANGES_BEFORE_EXIT 2006
+#define IDS_UNKNOWN 2007
+#define IDS_CHANGES_NOT_SAVED 2008
+#define IDS_MODERN 2009
+#define IDS_CLASSIC 2010
+#define IDS_QUIT_OK 2011
+#define IDS_PAGE_ASSOCIATIONS 2012
+#define IDS_FILETYPE_VIDEO 2013
+#define IDS_FILETYPE_AUDIO 2014
+#define IDS_FILETYPE_UNKNOWN 2015
+#define IDS_FILETYPE_PLAYLIST 2016
+#define IDS_PAGE_FEEDBACK 2017
+#define IDS_GENDER_MALE 2018
+#define IDS_GENDER_FEMALE 2019
+#define IDS_GENDER_UNKNOWN 2020
+#define IDS_REGISTER_CDPLAYER 2021
+#define IDS_STATUS_SAVING 2022
+#define IDS_STATUS_JOBS 2023
+#define IDS_STATUS_RUNWA 2024
+#define IDS_PAGE_SKIN_LONG 2025
+#define IDS_REGISTER_AGENT 2026
+#define IDS_PAGE_ASSOCIATIONS_LONG 2027
+#define IDS_PAGE_FEEDBACK_LONG 2028
+#define IDS_INCORRECT_EMAIL_ADDRESS 2029
+#define IDS_PAGE_INCORRECT_EMAIL_ADDRESS 2029
+#define IDS_FILETYPE_AUXILIARY 2030
+#define IDS_WINAMP_SKIN_MODERN 2031
+#define IDS_WINAMP_SKIN_CLASSIC 2032
+#define IDS_WINAMP_LANG_PACK 2033
+#define IDS_DOWNLOADSTATUS_INITIALIZING 2034
+#define IDS_DOWNLOADSTATUS_CONNECTING 2035
+#define IDS_DOWNLOADSTATUS_CONNECTED 2036
+#define IDS_DOWNLOADSTATUS_RECEIVING 2037
+#define IDS_DOWNLOADSTATUS_RECEIVINGPERCENT 2038
+#define IDS_DOWNLOADSTATUS_SUCCESS 2039
+#define IDS_DOWNLOADSTATUS_FAILED 2040
+#define IDS_DOWNLOADSTATUS_ABORTING 2041
+#define IDS_DOWNLOADSTATUS_ABORTED 2042
+#define IDS_SETUP_WND_TITLE 2043
+#define ID_CMD_SAVE 40003
+#define IDM_HELP_ABOUT 40008
+#define IDM_TOOLS_MIGRATE 40009
+#define IDM_TOOLS_REGISTERWINAMP 40010
+#define IDM_NAVIGATE_BACK 40011
+#define IDM_NAVIGATE_NEXT 40012
+#define IDM_FILE_SAVECHANGES 40013
+#define IDM_FILE_EXIT 40016
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 121
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/Winamp/setup/setupcommon.h b/Src/Winamp/setup/setupcommon.h
new file mode 100644
index 00000000..3073bd4e
--- /dev/null
+++ b/Src/Winamp/setup/setupcommon.h
@@ -0,0 +1,31 @@
+#ifndef NULLOSFT_WINAMP_SETUPCOMMON_HEADER
+#define NULLOSFT_WINAMP_SETUPCOMMON_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <wtypes.h>
+
+
+#ifndef LONGX86
+#ifdef _WIN64
+ #define LONGX86 LONG_PTR
+#else /*_WIN64*/
+ #define LONGX86 LONG
+#endif /*_WIN64*/
+#endif // LONGX86
+
+#ifdef __cplusplus
+ #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
+#else
+ #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
+#endif // __cplusplus
+
+#define SENDWAIPC(__ipcMsgId, __param) SENDMSG(hMainWindow, WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
+
+#define MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
+#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
+
+
+#endif // NULLOSFT_WINAMP_SETUPCOMMON_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/setupfactory.cpp b/Src/Winamp/setup/setupfactory.cpp
new file mode 100644
index 00000000..fdb417ef
--- /dev/null
+++ b/Src/Winamp/setup/setupfactory.cpp
@@ -0,0 +1,249 @@
+#include "./setupfactory.h"
+#include <api/service/waservicefactorybase.h>
+#include <api/service/services.h>
+#include "api.h"
+#include "gen.h"
+#include "main.h"
+
+#define GUID_DEFINE
+#include "./setup.h"
+#undef GUID_DEFINE
+
+//#include "./spage_lang.h"
+//#include "./spage_connect.h"
+#include "./spage_skin.h"
+#include "./spage_assoc.h"
+//#include "./spage_feedback.h"
+
+#include "./sjob_register.h"
+#include <shlwapi.h>
+
+class setup_factory : public waServiceFactory
+{
+public:
+ setup_factory();
+ virtual ~setup_factory();
+public:
+ int AddRef();
+ int Release();
+ FOURCC GetServiceType();
+ const char *GetServiceName();
+ GUID GetGUID();
+ void *GetInterface(int global_lock);
+ int SupportNonLockingInterface();
+ int ReleaseInterface(void *ifc);
+ const char *GetTestString();
+ int ServiceNotify(int msg, int param1, int param2);
+
+private:
+ int ref;
+ svc_setup *psvcSetup;
+protected:
+ RECVS_DISPATCH;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+BOOL Setup_RegisterService(void)
+{
+ setup_factory *psf = new setup_factory();
+ WASABI_API_SVC->service_register(psf);
+ return (0 != psf->Release());
+}
+
+int Setup_RegisterDefault(void)
+{
+ waServiceFactory *psf = WASABI_API_SVC->service_getServiceByGuid(UID_SVC_SETUP);
+ if (!psf) return 0;
+
+ svc_setup *pSvc = (svc_setup*)psf->getInterface();
+ if (pSvc)
+ {
+ int index = 0;
+ ifc_setuppage *pp;
+ ifc_setupjob *pj;
+ // pp = new setup_page_lang();
+ // if (pp) { pSvc->InsertPage(pp, &index); pp->Release(); }
+
+ pp = new setup_page_skin();
+ if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); }
+
+// pp = new setup_page_connect();
+// if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); }
+
+ pp = new setup_page_assoc();
+ if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); }
+
+ // disabled for 5.66
+// pp = new setup_page_feedback();
+// if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); }
+
+ pj = new setup_job_register();
+ if (pj) { pSvc->AddJob(pj); pj->Release(); }
+
+ pSvc->Release();
+ return 1;
+ }
+
+ return 0;
+}
+
+int Setup_RegisterPlugins(void)
+{
+ wchar_t dirstr[MAX_PATH] = {0};
+ WIN32_FIND_DATAW d = {0};
+ PathCombineW(dirstr, PLUGINDIR, L"GEN_*.DLL");
+
+ HANDLE h = FindFirstFileW(dirstr,&d);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ wchar_t temp[MAX_PATH] = {0};
+ PathCombineW(temp, PLUGINDIR, d.cFileName);
+ HINSTANCE hLib = LoadLibraryW(temp);
+ if (hLib)
+ {
+ winampGeneralPurposePluginGetter pr = (winampGeneralPurposePluginGetter) GetProcAddress(hLib,"winampGetGeneralPurposePlugin");
+ if (pr)
+ {
+ Plugin_RegisterSetup fn = (Plugin_RegisterSetup)GetProcAddress(hLib, "RegisterSetup");
+ if (NULL == fn || FALSE == fn(hLib, WASABI_API_SVC))
+ {
+ winampGeneralPurposePlugin *plugin = pr();
+ if (plugin && (plugin->version == GPPHDR_VER || plugin->version == GPPHDR_VER_U))
+ {
+ char desc[128] = {0};
+ lstrcpynA(desc, plugin->description, sizeof(desc));
+ if (desc[0] && !memcmp(desc, "nullsoft(", 9))
+ {
+ // we'll let this leak for all 3rd party plug-ins as some crash during
+ // setup when we try to unload the plug-in e.g gen_Wake_up_call.dll
+ FreeModule(hLib);
+ }
+ }
+ }
+ }
+ }
+ } while (FindNextFileW(h,&d));
+ FindClose(h);
+ }
+ return 1;
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+
+setup_factory::setup_factory() : ref(1), psvcSetup(NULL)
+{
+}
+
+setup_factory::~setup_factory()
+{
+ if (NULL != psvcSetup)
+ {
+ psvcSetup->Release();
+ }
+}
+
+int setup_factory::AddRef(void)
+{
+ return ++ref;
+}
+
+int setup_factory::Release(void)
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+FOURCC setup_factory::GetServiceType()
+{
+ return WaSvc::UNIQUE;
+}
+
+const char *setup_factory::GetServiceName()
+{
+ return "Setup Service";
+}
+
+GUID setup_factory::GetGUID()
+{
+ return UID_SVC_SETUP;
+}
+
+int setup_factory::SupportNonLockingInterface()
+{
+ return 1;
+}
+
+const char *setup_factory::GetTestString()
+{
+ return NULL;
+}
+
+int setup_factory::ServiceNotify(int msg, int param1, int param2)
+{
+ switch(msg)
+ {
+ case SvcNotify::ONREGISTERED:
+ AddRef();
+ break;
+ case SvcNotify::ONDEREGISTERED:
+ Release();
+ break;
+ }
+ return 1;
+}
+
+void *setup_factory::GetInterface(int global_lock)
+{
+ if (NULL == psvcSetup)
+ {
+ psvcSetup = WASetup::CreateInstance();
+ if (NULL == psvcSetup)
+ return NULL;
+ }
+
+ psvcSetup->AddRef();
+ return psvcSetup;
+}
+
+int setup_factory::ReleaseInterface(void *ifc)
+{
+ if (ifc == psvcSetup && NULL != psvcSetup)
+ {
+ if (0 == psvcSetup->Release())
+ psvcSetup = NULL;
+ }
+ return 1;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_factory
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType)
+CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName)
+CB(WASERVICEFACTORY_GETGUID, GetGUID)
+CB(WASERVICEFACTORY_GETINTERFACE, GetInterface)
+CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface)
+CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface)
+CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString)
+CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify)
+END_DISPATCH
+
diff --git a/Src/Winamp/setup/setupfactory.h b/Src/Winamp/setup/setupfactory.h
new file mode 100644
index 00000000..c3ccba1c
--- /dev/null
+++ b/Src/Winamp/setup/setupfactory.h
@@ -0,0 +1,19 @@
+#ifndef NULLSOFT_WINAMP_SETUP_FACTORY_HEADER
+#define NULLSOFT_WINAMP_SETUP_FACTORY_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+int Setup_RegisterService(void);
+int Setup_RegisterDefault(void);
+int Setup_RegisterPlugins(void);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+
+
+#endif // NULLSOFT_WINAMP_SETUP_FACTORY_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/sjob_register.cpp b/Src/Winamp/setup/sjob_register.cpp
new file mode 100644
index 00000000..9754b2d4
--- /dev/null
+++ b/Src/Winamp/setup/sjob_register.cpp
@@ -0,0 +1,84 @@
+#include "main.h"
+#include "../nu/AutoChar.h"
+#include "./sjob_register.h"
+#include "./httpgrab.h"
+
+setup_job_register::setup_job_register() : ref(1), hwndHttp(NULL)
+{
+}
+
+setup_job_register::~setup_job_register()
+{
+}
+
+size_t setup_job_register::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_job_register::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_job_register::Execute(HWND hwndText)
+{
+ if (!isInetAvailable()) return S_OK;
+ if (!config_newverchk2) return S_OK;
+
+ // TODO re-enable at some point as needed
+#if 0
+ char data[8192] = {0};
+ SecureZeroMemory(data, sizeof(data));
+
+ INT s = GetPrivateProfileInt("WinampReg", "RegDataLen", 0, INI_FILEA);
+ if (s> 0)
+ {
+ if (GetPrivateProfileStruct("WinampReg", "RegData2", data, s, INI_FILEA))
+ {
+ wchar_t szEmail[256] = {0};
+ GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, sizeof(szEmail));
+ }
+ // if (!*szEmail) return S_OK;
+ }
+
+ HWND hwndHost = BeginGrabHTTPText(hwndText, HTTPGRAB_USEWINDOWTEXT, &hwndHttp);
+ HRESULT hr = (SendMetrics(data, hwndHost)) ? S_OK : S_FALSE;
+ hwndHttp = NULL;
+ EndGrabHTTPText(hwndHost);
+ return hr;
+#else
+ return S_OK;
+#endif
+}
+
+HRESULT setup_job_register::Cancel(HWND hwndText)
+{
+ if (hwndHttp) SendMessageW(hwndHttp, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
+ (LPARAM)GetDlgItem(hwndHttp, IDCANCEL));
+ return S_OK;
+}
+
+HRESULT setup_job_register::IsCancelSupported()
+{
+ return S_OK;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_job_register
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPJOB_EXECUTE, Execute)
+CB(API_SETUPJOB_CANCEL, Cancel)
+CB(API_SETUPJOB_ISCANCELSUPPORTED, IsCancelSupported)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/sjob_register.h b/Src/Winamp/setup/sjob_register.h
new file mode 100644
index 00000000..b87eb2e9
--- /dev/null
+++ b/Src/Winamp/setup/sjob_register.h
@@ -0,0 +1,28 @@
+#ifndef WINAMP_REGISTER_SETUP_JOB_HEADER
+#define WINAMP_REGISTER_SETUP_JOB_HEADER
+
+#include "./ifc_setupjob.h"
+
+class setup_job_register: public ifc_setupjob
+{
+
+public:
+ setup_job_register();
+ virtual ~setup_job_register();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT Execute(HWND hwndText);
+ HRESULT Cancel(HWND hwndText);
+ HRESULT IsCancelSupported();
+private:
+ size_t ref;
+ HWND hwndHttp;
+
+protected:
+ RECVS_DISPATCH;
+};
+
+
+#endif //WINAMP_REGISTER_SETUP_JOB_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/skininfo.cpp b/Src/Winamp/setup/skininfo.cpp
new file mode 100644
index 00000000..906d6e2b
--- /dev/null
+++ b/Src/Winamp/setup/skininfo.cpp
@@ -0,0 +1,330 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./skininfo.h"
+#include "./loadimage.h"
+#include "./langutil.h"
+#include "./setup_resource.h"
+#include "./api.h"
+#include <../xml/obj_xml.h>
+#include <api/service/waServiceFactory.h>
+#include "../xml/ifc_xmlreadercallbacki.h"
+#include "minizip/unzip.h"
+#include "../nu/AutoChar.h"
+
+#define ZIP_BUFFER_SIZE 2048
+
+static wchar_t szClassic[64] = {0, };
+#define CLASSIC_NAME() ((!*szClassic) ? getStringW(IDS_CLASSIC_SKIN_NAME, szClassic, sizeof(szClassic)/sizeof(wchar_t)) : szClassic)
+
+static BOOL ExtractCurrentFile(unzFile f, LPCWSTR pszPath);
+static INT ZipProcessSkinInfo(unzFile f, LPCWSTR pszTemp, SKININFO *psi, LPSTR szSearch, INT cchSearch); // returns length of search
+
+class SkinXMLCallback : public ifc_xmlreadercallbackI
+{
+public:
+ SkinXMLCallback(SKININFO *psi, LPCWSTR pszSkinXML, LPWSTR pszImage, INT cchImage) // if pszIamge != NULL iamge path will be returned instead of loading image
+ {
+ this->psi = psi;
+ this->pszImage = pszImage;
+ this->cchImage = cchImage;
+ if (this->pszImage) *this->pszImage = 0x00;
+ StringCchCopyW(szPath, sizeof(szPath)/sizeof(wchar_t), pszSkinXML);
+ PathRemoveFileSpecW(szPath);
+ };
+ void xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *s);
+ void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
+
+protected:
+ SKININFO *psi;
+ wchar_t szPath[MAX_PATH*2];
+ LPWSTR pszImage;
+ INT cchImage;
+};
+
+static BOOL LoadXMLFile(obj_xml *parser, LPCWSTR pszFileName)
+{
+ HANDLE hFile = CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
+ if (INVALID_HANDLE_VALUE == hFile) return FALSE;
+
+ BOOL br (TRUE);
+ DWORD bytesRead=0;
+ do
+ {
+ BYTE buffer[1024] = {0};
+ bytesRead=0;
+ if (ReadFile(hFile, buffer, 1024, &bytesRead, NULL) && bytesRead)
+ {
+ if (parser->xmlreader_feed(buffer, bytesRead)!=API_XML_SUCCESS) { br = FALSE; break; }
+ }
+ else
+ {
+ if (parser->xmlreader_feed(0, 0) != API_XML_SUCCESS) { br = FALSE; break; }
+ bytesRead=0;
+ }
+ } while (bytesRead);
+
+ CloseHandle(hFile);
+ return br;
+}
+
+static BOOL ReadSkinInfo(LPCWSTR pszSkinXML, SKININFO *psi, LPWSTR pszImage, INT cchImage)
+{
+ waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
+ if (parserFactory)
+ {
+ obj_xml *parser = (obj_xml *)parserFactory->getInterface();
+ if (parser)
+ {
+ SkinXMLCallback cb(psi, pszSkinXML, pszImage, cchImage);
+ parser->xmlreader_registerCallback(L"WinampAbstractionLayer", &cb);
+ parser->xmlreader_registerCallback(L"WinampAbstractionLayer\fSkinInfo\f*", &cb);
+ parser->xmlreader_registerCallback(L"WasabiXML", &cb);
+ parser->xmlreader_registerCallback(L"WasabiXML\fSkinInfo\f*", &cb);
+ parser->xmlreader_registerCallback(L"SkinInfo*", &cb);
+
+ parser->xmlreader_open();
+ LoadXMLFile(parser, pszSkinXML);
+ parser->xmlreader_unregisterCallback(&cb);
+ parser->xmlreader_close();
+ parserFactory->releaseInterface(parser);
+ }
+ }
+
+ return TRUE;
+}
+
+void SkinXMLCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, L"WinampAbstractionLayer", -1, xmltag, -1) ||
+ CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, L"WasabiXML", -1, xmltag, -1))
+ {
+ const wchar_t *version = params->getItemValue(L"version");
+ if (version) StringCchCopyW(psi->szWasabiVer, SI_VERMAX, version);
+ else psi->szWasabiVer[0] = 0x00;
+ }
+}
+
+void SkinXMLCallback::xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *s)
+{
+ static const wchar_t *tags[] = { L"name", L"version", L"comment", L"author", L"email", L"homepage", L"screenshot" };
+ int cch, i, count = sizeof(tags)/sizeof(wchar_t*);
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ LPWSTR p;
+
+ for (i = 0; i < count; i++)
+ {
+ if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, tags[i], -1, xmltag, -1)) break;
+ }
+
+ switch(i)
+ {
+ case 0: p = psi->szName; cch = SI_NAMEMAX; break;
+ case 1: p = psi->szVersion; cch = SI_VERMAX; break;
+ case 2: p = (SIF_COMMENT & psi->fMask) ? psi->pszComment : NULL; cch = psi->cchComment; break;
+ case 3: p = psi->szAuthor; cch = SI_AUTHORMAX; break;
+ case 4: p = psi->szEmail; cch = SI_EMAILMAX; break;
+ case 5: p = psi->szHomePage; cch = SI_HOMEPAGEMAX; break;
+ case 6:
+ if ((SIF_PREVIEW & psi->fMask) && *s)
+ {
+ if (pszImage) StringCchCopyW(pszImage, cchImage, s);
+ else
+ {
+ wchar_t szPic[MAX_PATH*2] = {0};
+ psi->hPreview = WALoadImage(NULL, NULL, (PathIsRootW(s)) ? s : PathCombineW(szPic, szPath, s), FALSE);
+ }
+ }
+ return;
+ default: return;
+ }
+
+ if (p) StringCchCopyW(p, cch, s);
+}
+
+BOOL GetSkinInfo(LPCWSTR pszSkinPath, SKININFO *psi)
+{
+ wchar_t szBuffer[MAX_PATH*2] = {0};
+ if (!psi || sizeof(SKININFO) != psi->cbSize) return FALSE;
+ psi->type = SKIN_TYPE_UNKNOWN;
+
+ if (SIF_COMMENT & psi->fMask)
+ {
+ if (!psi->pszComment || !psi->cchComment) return FALSE;
+ psi->pszComment[0] = 0x00;
+ }
+ if (SIF_PREVIEW & psi->fMask) psi->hPreview = NULL;
+
+ if (!pszSkinPath || !*pszSkinPath || CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
+ pszSkinPath, -1, CLASSIC_NAME(), -1))
+ {
+ // default classic
+ psi->type = SKIN_TYPE_CLASSIC;
+ StringCchCopyW(psi->szName, SI_NAMEMAX, CLASSIC_NAME());
+
+ if (SIF_COMMENT & psi->fMask) StringCchCopyW(psi->pszComment, psi->cchComment, L"Winamp base skin v5.5");
+ if (SIF_PREVIEW & psi->fMask)
+ psi->hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_CLASSIC), FALSE);
+ StringCchCopyW(psi->szAuthor, SI_AUTHORMAX, L"Steve Gedikian");
+ StringCchCopyW(psi->szVersion, SI_VERMAX, L"2.0");
+ return TRUE;
+ }
+ if (PathIsDirectoryW(pszSkinPath))
+ {
+ if (PathFileExistsW(PathCombineW(szBuffer, pszSkinPath, L"skin.xml")))
+ {
+ psi->type = SKIN_TYPE_MODERN;
+ ReadSkinInfo(szBuffer, psi, NULL, 0);
+ }
+ else if (PathFileExistsW(PathCombineW(szBuffer, pszSkinPath, L"main.bmp")))
+ {
+ psi->type = SKIN_TYPE_CLASSIC;
+ ReadSkinInfo(PathCombineW(szBuffer, pszSkinPath, L"skininfo.xml"), psi, NULL, 0);
+ }
+ }
+ else
+ {
+ int len, start, lenSearch;
+ DWORD lcid;
+ wchar_t szTemp[MAX_PATH] = {0};
+ char filename[MAX_PATH] = {0}, search[MAX_PATH] = {0};
+ unzFile f;
+
+ if (!GetTempPathW(MAX_PATH, szBuffer) || !GetTempFileNameW(szBuffer, L"WAS", 0, szTemp)) return FALSE;
+
+ f = unzOpen(AutoChar(pszSkinPath));
+ if (!f) return FALSE;
+
+ lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ search[0] = 1;
+ lenSearch = 0;
+ start = 0;
+ do
+ {
+ int pos = -1, nr = unzGoToFirstFile(f);
+ while (UNZ_OK == nr && *search)
+ {
+ pos++;
+ if (start && pos == start) { start = 0; break; }
+ if (UNZ_OK == unzGetCurrentFileInfo(f, NULL, filename, sizeof(filename), NULL, 0, NULL, 0) && *filename)
+ {
+ len = lstrlenA(filename);
+ if (!len || filename[len - 1] == '/') // empty or folder
+ {
+ nr = unzGoToNextFile(f);
+ continue;
+ }
+ if (SKIN_TYPE_UNKNOWN == psi->type)
+ {
+ if ((len == 8 || (len > 8 && '/' == filename[len - 8 - 1])) &&
+ CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, "main.bmp", -1, (filename + (len - 8)), -1))
+ {
+ psi->type = SKIN_TYPE_CLASSIC;
+ StringCchCopyA(search, MAX_PATH, "skininfo.xml");
+ lenSearch = lstrlenA(search);
+ start = pos;
+ }
+ else if ((len == 8 || (len > 8 && '/' == filename[len - 8 - 1])) &&
+ CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, "skin.xml", -1, (filename + (len - 8)), -1))
+ {
+ psi->type = SKIN_TYPE_MODERN;
+ lenSearch = ZipProcessSkinInfo(f, szTemp, psi, search, MAX_PATH);
+ if (lenSearch) start = pos;
+ }
+ }
+ else if ((len == lenSearch || (len > lenSearch && '/' == filename[len - lenSearch - 1])) &&
+ CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, search, -1, (filename + (len - lenSearch)), -1))
+ {
+ if (CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, search, -1, "skininfo.xml", -1))
+ {
+ lenSearch = ZipProcessSkinInfo(f, szTemp, psi, search, MAX_PATH);
+ if (lenSearch) start = pos;
+ }
+ else // image
+ {
+ if (ExtractCurrentFile(f, szTemp)) psi->hPreview = WALoadImage(NULL, NULL, szTemp, FALSE);
+ else psi->hPreview = NULL;
+ *search = 0x00;
+ }
+ }
+ }
+ nr = unzGoToNextFile(f);
+ }
+ } while(search && *search && start);
+ unzClose(f);
+
+ // delete tmp file
+ DeleteFileW(szTemp);
+ }
+
+ return TRUE;
+}
+
+static BOOL ExtractCurrentFile(unzFile f, LPCWSTR pszPath)
+{
+ HANDLE hFile;
+ OVERLAPPED asyncIO;
+ static BOOL isNT = -1;
+ BOOL bSuccess(TRUE);
+
+ int l(1), pos(0), bufNum(0);
+ char buf[ZIP_BUFFER_SIZE*2] = {0};
+
+ if (UNZ_OK != unzOpenCurrentFile(f)) return FALSE;
+
+ if (-1 == isNT) isNT = (GetVersion() < 0x80000000);
+ ZeroMemory(&asyncIO, sizeof(OVERLAPPED));
+ if (isNT) asyncIO.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
+
+ hFile = CreateFileW(pszPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | ((isNT) ? FILE_FLAG_OVERLAPPED : 0), NULL);
+ if (INVALID_HANDLE_VALUE == hFile) { bSuccess = FALSE; hFile = NULL; }
+
+ while (bSuccess && l > 0)
+ {
+ DWORD written = 0;
+ bufNum = !bufNum;
+ l = unzReadCurrentFile(f, buf+ZIP_BUFFER_SIZE*bufNum, ZIP_BUFFER_SIZE);
+ if (l < 0) bSuccess = FALSE;
+ if (isNT)
+ {
+ WaitForSingleObject(asyncIO.hEvent, INFINITE);
+ if (l > 0)
+ {
+ asyncIO.Offset = pos;
+ if (!WriteFile(hFile, buf+ZIP_BUFFER_SIZE*bufNum, l, NULL, &asyncIO) && ERROR_IO_PENDING != GetLastError())
+ {
+ bSuccess = FALSE;
+ }
+ pos += l;
+ }
+ }
+ else
+ {
+ if (l > 0)
+ {
+ if (!WriteFile(hFile, buf+ZIP_BUFFER_SIZE*bufNum, l, &written, NULL)) bSuccess = FALSE;
+ }
+ }
+ }
+
+ if (hFile) CloseHandle(hFile);
+ if (asyncIO.hEvent) CloseHandle(asyncIO.hEvent);
+ unzCloseCurrentFile(f);
+ return bSuccess;
+}
+
+static INT ZipProcessSkinInfo(unzFile f, LPCWSTR pszTemp, SKININFO *psi, LPSTR szSearch, INT cchSearch) // returns length of search
+{
+ *szSearch = 0x00;
+ if (ExtractCurrentFile(f, pszTemp))
+ {
+ wchar_t szImage[MAX_PATH] = {0};
+ if (ReadSkinInfo(pszTemp, psi, szImage, MAX_PATH) && *szImage)
+ {
+ if(!PathIsRelativeW(szImage)) psi->hPreview = WALoadImage(NULL, NULL, szImage, FALSE);
+ else StringCchCopyA(szSearch, cchSearch, AutoChar(szImage));
+ }
+ }
+ return lstrlenA(szSearch);
+} \ No newline at end of file
diff --git a/Src/Winamp/setup/skininfo.h b/Src/Winamp/setup/skininfo.h
new file mode 100644
index 00000000..b96494db
--- /dev/null
+++ b/Src/Winamp/setup/skininfo.h
@@ -0,0 +1,38 @@
+#ifndef WINAMP_SKININFO_HEADER
+#define WINAMP_SKININFO_HEADER
+
+#include <windows.h>
+
+#define SIF_COMMENT 0x01
+#define SIF_PREVIEW 0x02
+
+#define SKIN_TYPE_UNKNOWN 0
+#define SKIN_TYPE_CLASSIC 1
+#define SKIN_TYPE_MODERN 2
+
+#define SI_NAMEMAX 32
+#define SI_VERMAX 16
+#define SI_AUTHORMAX 32
+#define SI_EMAILMAX 32
+#define SI_HOMEPAGEMAX 64
+
+typedef struct _SKININFO
+{
+ INT cbSize; // sizeof(SKININFO)
+ UINT fMask; // SIF_DESCRIPTION | SIF_PREVIEW
+ int type; // classic/modern
+ wchar_t szName[SI_NAMEMAX];
+ wchar_t szVersion[SI_VERMAX];
+ wchar_t szAuthor[SI_AUTHORMAX];
+ wchar_t szEmail[SI_EMAILMAX];
+ wchar_t szHomePage[SI_HOMEPAGEMAX];
+ wchar_t szWasabiVer[SI_VERMAX];
+ wchar_t *pszComment;
+ int cchComment;
+ HBITMAP hPreview; // preiew bitmap;
+}SKININFO;
+
+
+BOOL GetSkinInfo(LPCWSTR pszSkinPath, SKININFO *psi);
+
+#endif //WINAMP_SKININFO_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/smokingllama.png b/Src/Winamp/setup/smokingllama.png
new file mode 100644
index 00000000..e63b4c28
--- /dev/null
+++ b/Src/Winamp/setup/smokingllama.png
Binary files differ
diff --git a/Src/Winamp/setup/spage_assoc.cpp b/Src/Winamp/setup/spage_assoc.cpp
new file mode 100644
index 00000000..937284d6
--- /dev/null
+++ b/Src/Winamp/setup/spage_assoc.cpp
@@ -0,0 +1,1069 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "api.h"
+#include "./spage_assoc.h"
+#include "./setup_resource.h"
+#include "../nu/ns_wc.h"
+#include "../nu/AutoWide.h"
+#include "./langutil.h"
+#include "./setupcommon.h"
+#include "../playlist/svc_playlisthandler.h"
+#include <api/service/waservicefactorybase.h>
+#include "../Agave/URIHandler/svc_urihandler.h"
+#include <api/service/waservicefactory.h>
+#include <commctrl.h>
+
+#define MF_SELECTED 0x0001
+#define MF_TYPE_MASK 0xFF00
+#define MF_TYPE_REREAD 0xFF
+#define MF_TYPE_UNKNOWN 0x00
+#define MF_TYPE_AUDIO 0x01
+#define MF_TYPE_VIDEO 0x02
+#define MF_TYPE_PLAYLIST 0x03
+#define MF_TYPE_AUXILIARY 0x04
+
+#define ID_REGISTERCD ((TYPE_CATEGORIES_NUM) + 1)
+#define ID_REGISTERAGENT ((TYPE_CATEGORIES_NUM) + 2)
+
+#define SET_TYPE(_val, _type) ((_val) = ((_val) & ~MF_TYPE_MASK) | ((_type) << 8))
+#define GET_TYPE(_val) ((_val) >> 8)
+#define IS_NEEDREREAD(_val) GET_TYPE((_val), MF_TYPE_REREAD)
+#define IS_SELECTED(_val) (MF_SELECTED & (_val))
+#define INITMETA( _type, _selected) ((WORD)(((_type) << 8) | ((_selected) ? MF_SELECTED : 0x0000)))
+
+static wchar_t szAuxExt[] = L"wsz\0wal\0wlz\0";
+
+static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+static BOOL IsAgentScheduled(void)
+{
+ HKEY hKey = NULL;
+ BOOL bActive(FALSE);
+ WCHAR szAgent[MAX_PATH*2] = {0};
+ DWORD cb = sizeof(szAgent);
+
+ if (ERROR_SUCCESS != RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey))
+ return FALSE;
+ if (ERROR_SUCCESS != RegQueryValueExW(hKey, L"WinampAgent", NULL, NULL, (BYTE*)szAgent, &cb))
+ szAgent[0] = 0x00;
+ RegCloseKey(hKey);
+
+ if (*szAgent)
+ {
+ WCHAR szPath[MAX_PATH*2] = {0};
+ GetModuleFileNameW(NULL, szPath, sizeof(szPath)/sizeof(wchar_t));
+ PathUnquoteSpacesW(szAgent);
+ PathRemoveFileSpecW(szAgent);
+ PathRemoveFileSpecW(szPath);
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ bActive = (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, szPath, -1, szAgent, -1));
+ }
+
+ return bActive;
+}
+
+static BOOL IsAgentExist(void)
+{
+ wchar_t szAgent[MAX_PATH] = {0};
+ if (0 == GetModuleFileNameW(hMainInstance, szAgent, sizeof(szAgent)/sizeof(wchar_t)))
+ return FALSE;
+
+ PathRemoveFileSpecW(szAgent);
+ if (NULL == PathCombineW(szAgent, szAgent, L"winampa.exe"))
+ return FALSE;
+
+ return (FALSE != PathFileExistsW(szAgent));
+}
+
+static BOOL RefreshIcons(void)
+{
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, NULL, NULL);
+ return TRUE;
+}
+
+static void RegisterProtocols()
+{
+ if (config_no_registry)
+ return;
+
+ wchar_t winampexe[MAX_PATH] = {0};
+ GetModuleFileNameW(hMainInstance, winampexe, MAX_PATH);
+
+ WCHAR szApplication[256] = {0};
+ INT r = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, NULL, 0);
+ if (r > ARRAYSIZE(szApplication) || 0 == r)
+ return;
+ if (0 == MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, szApplication, ARRAYSIZE(szApplication)))
+ return;
+
+ if (NULL != WASABI_API_SVC)
+ {
+ for(size_t i =0;;i++)
+ {
+ waServiceFactory *sf = WASABI_API_SVC->service_enumService(svc_urihandler::getServiceType(), i);
+ if (NULL == sf) break;
+
+ svc_urihandler *handler = (svc_urihandler *)sf->getInterface();
+ if (NULL != handler)
+ {
+ WCHAR szName[128] = {0}, szDesc[256] = {0};
+ for (size_t k = 0; ;k++)
+ {
+ INT ret = handler->EnumProtocols(k, szName, ARRAYSIZE(szName), szDesc, ARRAYSIZE(szDesc));
+ if (0 != ret)
+ break;
+
+ if (0 == handler->RegisterProtocol(szName, winampexe))
+ {
+ IFileTypeRegistrar *registrar = 0;
+ if (GetRegistrar(&registrar, true) == 0 && registrar)
+ {
+ registrar->RegisterMediaPlayerProtocol(szName, szApplication);
+ registrar->Release();
+ }
+ }
+ }
+ sf->releaseInterface(handler);
+ }
+ }
+ }
+}
+
+setup_page_assoc::setup_page_assoc() : ref(1), hwnd(NULL), pszTypes(NULL), pMeta(NULL), bRegCD(FALSE), bAgent(FALSE), bExplorerMenu(TRUE)
+{
+ ZeroMemory(expanded, sizeof(expanded));
+ ZeroMemory(szTopExt, sizeof(szTopExt));
+ ZeroMemory(szCaretExt, sizeof(szCaretExt));
+}
+
+setup_page_assoc::~setup_page_assoc()
+{
+ if (pszTypes)
+ {
+ free(pszTypes);
+ pszTypes = NULL;
+ }
+ if (pMeta)
+ {
+ free(pMeta);
+ pMeta = NULL;
+ }
+}
+
+size_t setup_page_assoc::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_page_assoc::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_page_assoc::GetName(bool bShort, const wchar_t **pszName)
+{
+ if (bShort)
+ {
+ static wchar_t szShortName[32] = {0};
+ *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_ASSOCIATIONS, szShortName, sizeof(szShortName)/sizeof(wchar_t));
+ }
+ else
+ {
+ static wchar_t szLongName[64] = {0};
+ *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_ASSOCIATIONS_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t));
+ }
+ return S_OK;
+}
+
+HRESULT setup_page_assoc::Save(HWND hwndText)
+{
+ HRESULT hr(S_OK);
+ WORD *pm;
+ wchar_t ext_list[16384] = {0}, *p = 0, *pe = ext_list;
+ BOOL bFirst(TRUE);
+ size_t len = ARRAYSIZE(ext_list);
+
+ // make sure that we honour the agent setting even if no settings changed
+ // this allows the agent to be restarted correctly after a normal upgrade
+ if (bAgent && IsAgentExist())
+ config_agent_add();
+ else
+ config_agent_remove();
+
+ // temporary: always enumerate and register protocols
+ RegisterProtocols();
+
+ if (S_FALSE == IsDirty()) return S_OK;
+
+ if (!pszTypes) return S_FALSE;
+
+ config_setup_filetypes(0);
+
+ for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++)
+ {
+ config_register_capability(p, 0);
+ config_register(p, IS_SELECTED(*pm));
+ if (IS_SELECTED(*pm) && (S_OK == hr) && GET_TYPE(*pm) != MF_TYPE_AUXILIARY)
+ {
+ if (!len) { hr = S_FALSE; continue; }
+ if (!bFirst)
+ {
+ pe[0] = L':';
+ pe++;
+ len--;
+ }
+ else bFirst = FALSE;
+ if (S_OK != StringCchCopyExW(pe, len, p, &pe, &len, STRSAFE_IGNORE_NULLS)) hr = S_FALSE;
+ }
+ }
+ if (S_OK == hr) _w_sW("config_extlist", ext_list);
+
+ config_regcdplayer(bRegCD, 0);
+ (bExplorerMenu) ? config_adddircontext(0) : config_removedircontext(0);
+
+ config_registermediaplayer(1);
+
+ WritePrivateProfileStringW(L"Jump To File Extra", L"newIconLib", L"refresh", INI_FILE);
+ RefreshIcons();
+
+ return hr;
+}
+
+static BOOL IsFirstSetup()
+{
+ wchar_t szVer[512] = {0};
+ if (0 == GetPrivateProfileIntW(L"WinampReg", L"IsFirstInst", 1, INI_FILE)) return FALSE;
+
+ GetPrivateProfileStringW(L"Winamp", L"config_extlist", L"", szVer, 512, INI_FILE);
+ if (*szVer) return FALSE;
+
+ GetPrivateProfileStringW(L"WinampReg", L"WAVer", L"", szVer, 512, INI_FILE);
+ return (!*szVer || CSTR_EQUAL != CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+ NORM_IGNORECASE, szVer, -1, AutoWide(APP_VERSION), -1));
+}
+
+static wchar_t *BuildExtensionString(WORD **ppMeta, BOOL bFirstSetup)
+{
+ INT cWA(0), cPL(0), cAux(0), lWA(0), lPL(0), lAux(0);
+ wchar_t *pszType, *pWAExt = in_getextlistW(), *pPLExt, *p;
+
+ if (pWAExt)
+ {
+ for(p = pWAExt; *p != 0; cWA++, p += lstrlenW(p) + 1);
+ lWA = (INT)(p - pWAExt);
+ }
+
+ if (playlistManager)
+ {
+ size_t playlistEnum = 0;
+ const wchar_t *playlistExt=0;
+ while (NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++))) { lPL += (lstrlenW(playlistExt) + 1); cPL++; }
+ lPL += 2;
+ }
+
+ for(p = szAuxExt; *p != 0; cAux++, p += lstrlenW(p) + 1);
+ lAux = (INT)(p - szAuxExt);
+
+ pszType = (wchar_t*)calloc((lWA + lPL + lAux + 1), sizeof(wchar_t));
+ if (ppMeta)
+ {
+ *ppMeta = (WORD*)calloc((cWA + cPL + cAux), sizeof(WORD));
+ }
+
+ if (pszType)
+ {
+ if (pWAExt) CopyMemory(pszType, pWAExt, lWA*sizeof(wchar_t));
+ pPLExt = pszType + lWA;
+ p = pPLExt;
+ if (playlistManager)
+ {
+ size_t playlistEnum=0;
+ const wchar_t *playlistExt=0;
+ while (lPL > 0 && NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++)))
+ {
+ int c = lstrlenW(playlistExt) + 1;
+ lstrcpynW(p, playlistExt, c);
+ if (c)
+ {
+ p += c;
+ lPL -= c;
+ }
+ }
+ if (lPL > 1) *p = 0x00;
+ }
+ CopyMemory(p, szAuxExt, lAux*sizeof(wchar_t));
+ *(p+lAux)=0;
+ }
+
+ if(ppMeta && *ppMeta)
+ {
+ int i;
+ WORD *pm = *ppMeta;
+ p = pszType;
+ for (i = 0; i < cWA; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_REREAD, ((!bFirstSetup) ? config_isregistered(p) : 1));
+ for (i = 0; i < cPL; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_PLAYLIST, ((!bFirstSetup) ? config_isregistered(p) : 1));
+ for (i = 0; i < cAux; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_AUXILIARY, ((!bFirstSetup) ? config_isregistered(p) : 1));
+ }
+
+ if (pWAExt) GlobalFree(pWAExt);
+
+ return pszType;
+}
+
+static BOOL GetPLExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest)
+{
+ BOOL result(FALSE);
+ int n(0);
+ waServiceFactory *sf = 0;
+ LPCWSTR ext;
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+
+ while (NULL != (sf = WASABI_API_SVC->service_enumService(WaSvc::PLAYLISTHANDLER, n++)))
+ {
+ svc_playlisthandler * handler = static_cast<svc_playlisthandler *>(sf->getInterface());
+ if (handler)
+ {
+ int k(0);
+ while (NULL != (ext = handler->EnumerateExtensions(k++)))
+ {
+ if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, ext, -1))
+ {
+ result = (S_OK == StringCchCopyW(pszDest, cchDest, handler->GetName()));
+ if (result && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"M3U8", -1)) // ugly...
+ result = (S_OK == StringCchCatW(pszDest, cchDest, L" (Unicode)"));
+ break;
+ }
+ }
+ sf->releaseInterface(handler);
+ }
+ }
+ return result;
+}
+
+static BOOL GetAuxExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest)
+{
+ BOOL result(FALSE);
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wal", -1))
+ result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_MODERN, NULL, 0)));
+ else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wsz", -1))
+ result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_CLASSIC, NULL, 0)));
+ else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wlz", -1))
+ result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_LANG_PACK, NULL, 0)));
+ return result;
+}
+
+static BOOL GetExtensionName(LPCWSTR pszFile, INT type, LPWSTR pszDest, INT cchDest)
+{
+ switch(type)
+ {
+ case MF_TYPE_AUDIO:
+ case MF_TYPE_VIDEO:
+ return in_get_extended_fileinfoW(pszFile, L"family", pszDest, cchDest);
+ case MF_TYPE_PLAYLIST:
+ {
+ const wchar_t *pszExt = PathFindExtensionW(pszFile);
+ return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetPLExtensionName(pszExt, pszDest, cchDest) : FALSE;
+ }
+ case MF_TYPE_AUXILIARY:
+ {
+ const wchar_t *pszExt = PathFindExtensionW(pszFile);
+ return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetAuxExtensionName(pszExt, pszDest, cchDest) : FALSE;
+ }
+ }
+ return FALSE;
+}
+
+HRESULT setup_page_assoc::Revert(void)
+{
+ HRESULT hr(S_OK);
+
+ if (pszTypes)
+ {
+ free(pszTypes);
+ pszTypes = NULL;
+ }
+
+ if (pMeta)
+ {
+ free(pMeta);
+ pMeta = NULL;
+ }
+
+ BOOL firstSetup = IsFirstSetup();
+ pszTypes = BuildExtensionString(&pMeta, firstSetup);
+
+ ZeroMemory(expanded, sizeof(expanded));
+ ZeroMemory(szTopExt, sizeof(szTopExt));
+ ZeroMemory(szCaretExt, sizeof(szCaretExt));
+
+ bRegCD = (firstSetup) ? TRUE : config_iscdplayer();
+ bAgent = (FALSE != IsAgentExist()) ? ((firstSetup) ? FALSE : IsAgentScheduled()) : FALSE;
+ bExplorerMenu = (firstSetup) ? TRUE : config_isdircontext();
+
+ if (hwnd) UpdateUI();
+ return hr;
+}
+
+HRESULT setup_page_assoc::IsDirty(void)
+{
+ if (IsFirstSetup()) return S_OK;
+
+ HRESULT hr(S_FALSE);
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ wchar_t *pszOrigTypes = BuildExtensionString(NULL, TRUE), *p;
+ if ((!pszOrigTypes && pszTypes) || (pszOrigTypes && !pszTypes))
+ {
+ if (pszOrigTypes) free(pszOrigTypes);
+ return S_OK;
+ }
+ else if (!pszOrigTypes && !pszTypes) return S_FALSE;
+
+ INT cr = CompareStringW(lcid, NORM_IGNORECASE, pszTypes, -1, pszOrigTypes, -1);
+ if (0 == cr) hr = E_UNEXPECTED;
+ else if (CSTR_EQUAL == cr)
+ {
+ WORD *pm;
+ for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++)
+ {
+ if ((MF_SELECTED & *pm) != (BYTE)config_isregistered(p)) { hr = S_OK; break; }
+ }
+ }
+ else hr = S_OK;
+
+ if (pszOrigTypes) free(pszOrigTypes);
+
+ if (S_FALSE == hr && bRegCD != config_iscdplayer()) hr = S_OK;
+ if (S_FALSE == hr && bAgent != (IsAgentExist() && IsAgentScheduled())) hr = S_OK;
+ if (S_FALSE == hr && bExplorerMenu != config_isdircontext()) hr = S_OK;
+
+ return hr;
+}
+
+HRESULT setup_page_assoc::Validate(void)
+{
+ return S_OK;
+}
+
+HRESULT setup_page_assoc::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ *phwnd = WACreateDialogParam(MAKEINTRESOURCEW((!IsWin8() ? IDD_SETUP_PAGE_ASSOC : IDD_SETUP_PAGE_ASSOC_WIN8)), hwndParent, ::DialogProc, (LPARAM)this);
+ return S_OK;
+}
+
+void setup_page_assoc::UpdateUI(void)
+{
+ TVINSERTSTRUCTW is = {0};
+ WORD *pm;
+ HTREEITEM hBranch[TYPE_CATEGORIES_NUM], hFirst(NULL), hCaret(NULL), hItem;
+ INT sBranch[TYPE_CATEGORIES_NUM] = {0};
+ INT ids[TYPE_CATEGORIES_NUM] = {IDS_FILETYPE_UNKNOWN, IDS_FILETYPE_AUDIO, IDS_FILETYPE_VIDEO, IDS_FILETYPE_PLAYLIST, IDS_FILETYPE_AUXILIARY};
+ INT i;
+
+ wchar_t szText[MAX_PATH] = {0}, buf[MAX_PATH] = {0}, buf2[MAX_PATH] = {0}, *p, *test;
+ if (!hwnd || !IsWindow(hwnd)) return;
+
+ DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+
+ HWND hwndTree = GetDlgItem(hwnd,IDC_TREE_TYPES);
+ SendMessageW(hwndTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
+ if (!pszTypes) return;
+
+ for (i = 0; i < ARRAYSIZE(hBranch); i++)
+ {
+ hBranch[i] = NULL;
+ sBranch[i] = -1;
+ }
+
+ INT len = ARRAYSIZE(buf);
+ StringCchCopyW(buf, len, L"test.");
+ test = buf + lstrlenW(buf);
+ len -= (INT)(test - buf);
+
+ SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L);
+
+ is.hInsertAfter = TVI_LAST;
+ is.item.mask = TVIF_STATE | TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM;
+ is.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED;
+ for(i = 0, pm = pMeta, p = pszTypes; *p != 0 && *(p+1) != 0; pm++, p += lstrlenW(p) + 1, i++)
+ {
+ StringCchCopyW(test, len, p);
+ OutputDebugStringW(test);
+ OutputDebugStringW(L"\r\n");
+ if (MF_TYPE_REREAD == GET_TYPE(*pm))
+ {
+ if (!in_get_extended_fileinfoW(buf, L"type", buf2, MAX_PATH))
+ ZeroMemory(buf2, sizeof(buf2));
+
+ *pm = *pm & 0x00FF;
+ switch(buf2[0])
+ {
+ case L'0': SET_TYPE(*pm, MF_TYPE_AUDIO); break;
+ case L'1': SET_TYPE(*pm, MF_TYPE_VIDEO); break;
+ }
+ }
+
+ INT index = GET_TYPE(*pm);
+ if (!hBranch[index])
+ {
+ is.hInsertAfter = TVI_SORT;
+ is.hParent = TVI_ROOT;
+ is.item.cChildren = 1;
+ is.item.state = INDEXTOSTATEIMAGEMASK(1) | ((expanded[index]) ? TVIS_EXPANDED : 0);
+ is.item.pszText = getStringW(ids[index], NULL, 0);
+ is.item.lParam = -(index + 1);
+ hBranch[index] = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
+ is.item.cChildren = 0;
+ is.hInsertAfter = TVI_LAST;
+
+ wchar_t t[32] = {0};
+ StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", index + 1);
+ if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hBranch[index];
+ if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hBranch[index];
+ }
+
+ is.hParent = hBranch[index];
+
+ if (MF_SELECTED & *pm)
+ {
+ if (-1 == sBranch[index]) sBranch[index] = 1;
+ else if (0 == sBranch[index]) sBranch[index] = 2;
+ }
+ else
+ {
+ if (-1 == sBranch[index]) sBranch[index] = 0;
+ else if (1 == sBranch[index]) sBranch[index] = 2;
+ }
+
+ lstrcpynW(szText, p, MAX_PATH);
+ INT count = lstrlenW(szText);
+ CharUpperW(szText);
+ wchar_t szName[MAX_PATH] = {0};
+ if (GetExtensionName(buf, GET_TYPE(*pm), szName, MAX_PATH))
+ {
+ if (count) StringCchCatW(szText, MAX_PATH, L"\t");
+ StringCchCatW(szText, MAX_PATH, szName);
+ }
+
+ is.item.pszText = szText;
+ is.item.lParam = (LPARAM)i;
+ is.item.state = INDEXTOSTATEIMAGEMASK((MF_SELECTED & *pm)?2:1);
+
+ hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
+
+ if (hItem)
+ {
+ if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szTopExt, -1)) hFirst = hItem;
+ if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szCaretExt, -1)) hCaret = hItem;
+ }
+ }
+
+ // insert cd
+ is.hParent = TVI_ROOT;
+ is.item.state = INDEXTOSTATEIMAGEMASK(bRegCD + 1);
+ is.item.pszText = getStringW(IDS_REGISTER_CDPLAYER, NULL, 0);
+ is.item.lParam = -ID_REGISTERCD;
+ hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is);
+ if (!hFirst || !hCaret)
+ {
+ wchar_t t[32] = {0};
+ StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", ID_REGISTERCD);
+ if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hItem;
+ if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hItem;
+ }
+
+ // agent
+ BOOL bAgentExist = IsAgentExist();
+ HWND hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT);
+ if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist);
+ hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC);
+ if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist);
+
+ CheckDlgButton(hwnd, IDC_CHK_AGENT, (bAgent && bAgentExist) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_CD, (bRegCD) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_EXPLORER_MENU, (bExplorerMenu) ? BST_CHECKED : BST_UNCHECKED);
+
+ is.item.mask = TVIF_STATE;
+ is.item.stateMask = TVIS_STATEIMAGEMASK;
+
+ for (int i = 0; i < sizeof(hBranch)/sizeof(HTREEITEM); i++)
+ {
+ if (!hBranch[i]) continue;
+ is.item.hItem = hBranch[i];
+ is.item.state = INDEXTOSTATEIMAGEMASK(sBranch[i] + 1);
+ SendMessageW(hwndTree, TVM_SETITEM, 0, (LPARAM)&is.item);
+ SendMessageW(hwndTree, TVM_SORTCHILDREN, FALSE, (LPARAM)hBranch[i]);
+ }
+
+ if (hCaret) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hCaret);
+ if (hFirst) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hFirst);
+
+ SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L);
+}
+
+INT setup_page_assoc::TreeView_OnCustomDraw(NMTVCUSTOMDRAW *ptvcd)
+{
+ switch(ptvcd->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ return CDRF_DODEFAULT | CDRF_NOTIFYITEMDRAW;
+ case CDDS_ITEMPREPAINT:
+ return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT;
+ case CDDS_ITEMPOSTPAINT:
+ {
+ RECT rt;
+ WCHAR szText[256] = {0};
+ TVITEMW item = {0};
+
+ item.hItem = (HTREEITEM)ptvcd->nmcd.dwItemSpec;
+ item.mask = TVIF_TEXT | TVIF_STATE;
+ item.stateMask = TVIS_SELECTED;
+ item.pszText = szText;
+ item.cchTextMax = 256;
+ SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMW, 0, (LPARAM)&item);
+ *(DWORD_PTR*)&rt = ptvcd->nmcd.dwItemSpec;
+ SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rt);
+ SetTextColor(ptvcd->nmcd.hdc, ptvcd->clrText);
+ SetBkColor(ptvcd->nmcd.hdc, ptvcd->clrTextBk);
+
+ DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT);
+ rt.right += 8;
+ rt.top = ptvcd->nmcd.rc.top;
+ rt.bottom = ptvcd->nmcd.rc.bottom;
+
+ ExtTextOutW(ptvcd->nmcd.hdc, 0, 0, ETO_OPAQUE, &rt, L"", 0, NULL);
+ rt.left += 4;
+ DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
+
+ if ((TVIS_SELECTED & item.state) && ptvcd->nmcd.hdr.hwndFrom == GetFocus())
+ {
+ if (0 == (0x01/*UISF_HIDEFOCUS*/ & SendMessageW(ptvcd->nmcd.hdr.hwndFrom, 0x0129/*WM_QUERYUISTATE*/, 0, 0L)))
+ {
+ rt.left -= 4;
+ SetTextColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT));
+ SetBkColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOW));
+ DrawFocusRect(ptvcd->nmcd.hdc, &rt);
+ }
+ }
+ }
+ break;
+ }
+ return CDRF_DODEFAULT;
+}
+
+BOOL setup_page_assoc::TreeView_OnClick(NMHDR *pnmh)
+{
+ TVHITTESTINFO ht;
+ GetCursorPos(&ht.pt);
+ MapWindowPoints(HWND_DESKTOP, pnmh->hwndFrom, &ht.pt, 1);
+ if(NULL != SendMessageW(pnmh->hwndFrom, TVM_HITTEST, 0, (LPARAM)&ht))
+ {
+ if ((TVHT_ONITEM | TVHT_ONITEMRIGHT) & ht.flags)
+ {
+ TreeView_OnItemStateClick(pnmh->hwndFrom, ht.hItem);
+ if (TVHT_ONITEMSTATEICON & ht.flags) return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL setup_page_assoc::TreeView_OnKeyDown(NMTVKEYDOWN *ptvkd)
+{
+ switch(ptvkd->wVKey)
+ {
+ case VK_SPACE:
+ {
+ HTREEITEM hItem = (HTREEITEM)(HTREEITEM)SendMessageW(ptvkd->hdr.hwndFrom, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L);
+ if (hItem) TreeView_OnItemStateClick(ptvkd->hdr.hwndFrom, hItem);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void setup_page_assoc::TreeView_OnItemStateClick(HWND hwndTree, HTREEITEM hItem)
+{
+ HTREEITEM hParent = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)hItem);
+ HTREEITEM hChild = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem);
+ TVITEMW item = {0};
+ item.hItem = hItem;
+ item.mask = TVIF_STATE | TVIF_PARAM;
+ item.stateMask = TVIS_STATEIMAGEMASK;
+
+ if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) return;
+ INT state = ((item.state>>12) - 1);
+ INT param = (INT)item.lParam;
+
+ SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L);
+
+ state = (2 == state) ? 1 : !state;
+
+ item.mask = TVIF_STATE;
+ item.state = INDEXTOSTATEIMAGEMASK(state + 1);
+ SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
+
+ if (!hChild)
+ {
+ INT count = 1, selcount = state;
+
+ item.hItem = hItem;
+ while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PREVIOUS, (LPARAM)item.hItem)))
+ {
+ count++;
+ if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue;
+ if (2 == (item.state>>12)) selcount++;
+ }
+ item.hItem = hItem;
+ while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem)))
+ {
+ count++;
+ if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue;
+ if (2 == (item.state>>12)) selcount++;
+ }
+
+ item.hItem = hParent;
+ item.state = INDEXTOSTATEIMAGEMASK(((!selcount) ? 1 : ((selcount == count) ? 2 :3)));
+ SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
+ if (param >= 0) pMeta[param] = (pMeta[param] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0);
+ else
+ {
+ switch(-param)
+ {
+ case ID_REGISTERCD: bRegCD = state; break;
+ }
+ }
+ }
+ else
+ {
+ item.hItem = hChild;
+ while(item.hItem)
+ {
+ item.mask = TVIF_PARAM;
+ if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item) && item.lParam >= 0) pMeta[item.lParam] = (pMeta[item.lParam] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0);
+
+ item.mask = TVIF_STATE;
+ item.state = INDEXTOSTATEIMAGEMASK(state + 1);
+ SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item);
+ item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem);
+ }
+ }
+ UpdateWindow(hwnd);
+ SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
+ SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L);
+ SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
+ InvalidateRect(hwndTree, NULL, FALSE);
+}
+
+INT_PTR setup_page_assoc::OnInitDialog(HWND hwndFocus, LPARAM lParam)
+{
+ HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES);
+ if (hwndTree)
+ {
+ HIMAGELIST himl = ImageList_LoadImage(hMainInstance, MAKEINTRESOURCE(IDB_CHECKBOX), 16, 1, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_LOADTRANSPARENT);
+ if (himl) himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)himl);
+ if (himl) ImageList_Destroy(himl);
+
+ WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)TreeViewProc);
+ if (fnOldProc) SetPropW(hwndTree, L"TVPROC", fnOldProc);
+ }
+ UpdateUI();
+ return 0;
+}
+
+void setup_page_assoc::OnDestroy(void)
+{
+ HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES);
+ if (hwndTree)
+ {
+ TVITEMW item = {0};
+ HIMAGELIST himl;
+ INT index1(-1), index2(-1);
+ wchar_t *p;
+
+ ZeroMemory(expanded, sizeof(expanded));
+ ZeroMemory(szTopExt, sizeof(szTopExt));
+ ZeroMemory(szCaretExt, sizeof(szCaretExt));
+
+ item.mask = TVIF_PARAM | TVIF_STATE;
+ item.stateMask = TVIS_EXPANDED;
+ item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, 0L);
+ while(item.hItem)
+ {
+ if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item))
+ {
+ INT param = (INT)-item.lParam;
+ if (param < TYPE_CATEGORIES_NUM) expanded[param] = (BYTE)(TVIS_EXPANDED & item.state);
+ }
+ item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem);
+ }
+ item.mask = TVIF_PARAM;
+ item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_FIRSTVISIBLE, 0L);
+ if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index1 = (INT)item.lParam;
+ item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L);
+ if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index2 = (INT)item.lParam;
+
+ if (index1 < 0) StringCchPrintfW(szTopExt, ARRAYSIZE(szTopExt), L"#%d", -index1);
+ if (index2 < 0) StringCchPrintfW(szCaretExt, ARRAYSIZE(szCaretExt), L"#%d", -index2);
+
+ if (index1 >= 0 || index2 >= 0)
+ {
+ INT i;
+ for(i = 0, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, i++)
+ {
+ if (index1 == i)
+ {
+ StringCchCopyW(szTopExt, ARRAYSIZE(szTopExt), p);
+ if (index2 < 0) break;
+ index1 = -1;
+ }
+ if (index2 == i)
+ {
+ StringCchCopyW(szCaretExt, ARRAYSIZE(szCaretExt), p);
+ if (index1 < 0) break;
+ index2 = -1;
+ }
+ }
+ }
+ himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)NULL);
+ if (himl) ImageList_Destroy(himl);
+ }
+}
+
+void setup_page_assoc::OnSize(UINT nType, INT cx, INT cy)
+{
+ RECT rw;
+ INT h, r;
+ h = cy;
+ r = cx;
+
+ HWND hwndCtrl = GetDlgItem(hwnd, IDC_LBL_HEADER);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, 0, 0, cx - rw.left*2, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
+ }
+
+ if (IsWin8())
+ {
+ // hide the treeview (as needed to process things nicely but needs to be hidden on Windows 8 and higher as they work differently)
+ hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES);
+ if (hwndCtrl)
+ {
+ SetWindowPos(hwndCtrl, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW);
+ }
+ return;
+ }
+
+ hwndCtrl = GetDlgItem(hwnd, IDC_CHK_EXPLORER_MENU);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ h = cy - (((rw.bottom - rw.top)*3) + 6);
+ r = max(0, (cx - (rw.right - rw.left))/2) + (rw.right - rw.left);
+ SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
+ h, rw.right - rw.left + 26,
+ rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
+
+ }
+ hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
+ h + (rw.bottom - rw.top) + 2,
+ rw.right - rw.left + 26,
+ rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+ hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
+ h + (rw.bottom - rw.top)*2 + 2,
+ rw.right - rw.left + 26,
+ rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+ hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12,
+ rw.top, rw.right - rw.left + 26,
+ h - rw.top - 4, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+}
+
+void setup_page_assoc::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDC_CHK_EXPLORER_MENU:
+ {
+ switch (nEvntID)
+ {
+ case BN_CLICKED:
+ bExplorerMenu = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
+ break;
+ }
+ break;
+ }
+ case IDC_CHK_AGENT:
+ {
+ switch (nEvntID)
+ {
+ case BN_CLICKED:
+ bAgent = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
+ break;
+ }
+ break;
+ }
+ case IDC_CHK_CD:
+ {
+ switch (nEvntID)
+ {
+ case BN_CLICKED:
+ bRegCD = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)));
+ break;
+ }
+ break;
+ }
+ }
+}
+
+BOOL setup_page_assoc::OnNotify(INT nCtrlID, NMHDR *pnmh, LRESULT *pResult)
+{
+ switch(nCtrlID)
+ {
+ case IDC_TREE_TYPES:
+ switch(pnmh->code)
+ {
+ case NM_CUSTOMDRAW: *pResult = TreeView_OnCustomDraw((NMTVCUSTOMDRAW*)pnmh); return TRUE;
+ case NM_CLICK: *pResult = TreeView_OnClick(pnmh); return TRUE;
+ case TVN_KEYDOWN: *pResult = TreeView_OnKeyDown((NMTVKEYDOWN*)pnmh); return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+INT_PTR setup_page_assoc::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: OnDestroy(); break;
+ case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break;
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ case WM_NOTIFY:
+ {
+ LRESULT result = 0;
+ if (OnNotify((INT)wParam, (NMHDR*)lParam, &result))
+ {
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)(LONG_PTR)result);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ setup_page_assoc *pInst = (setup_page_assoc*)GetPropW(hwnd, L"SETUPPAGE");
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ pInst = (setup_page_assoc*)lParam;
+ if (pInst)
+ {
+ pInst->hwnd = hwnd;
+ SetPropW(hwnd, L"SETUPPAGE", pInst);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->PageDlgProc(uMsg, wParam, lParam);
+ RemovePropW(hwnd, L"SETUPPAGE");
+ pInst = NULL;
+ }
+ break;
+ }
+
+ return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
+}
+
+static void TreeViewCheckItems(HWND hwnd, TVITEMW *pItem)
+{
+ while (pItem->hItem)
+ {
+ SendMessageW(hwnd, TVM_SETITEMW, 0, (LPARAM)pItem);
+ HTREEITEM hChild = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)pItem->hItem);
+ if (hChild)
+ {
+ HTREEITEM hTemp = pItem->hItem;
+ pItem->hItem = hChild;
+ TreeViewCheckItems(hwnd, pItem);
+ pItem->hItem = hTemp;
+ }
+ pItem->hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_NEXT, (LPARAM)pItem->hItem);
+ }
+}
+
+static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"TVPROC");
+ if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ RemovePropW(hwnd, L"TVPROC");
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)fnOldProc);
+ break;
+
+ case WM_CHAR:
+ if (0x01/*(CTRL_A)*/ == wParam)
+ {
+ TVITEMW item = {0};
+ item.mask = TVIF_HANDLE | TVIF_STATE;
+ item.stateMask = TVIS_STATEIMAGEMASK;
+ item.state = INDEXTOSTATEIMAGEMASK(2);
+ item.hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_ROOT, 0L);
+ SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
+ TreeViewCheckItems(hwnd, &item);
+ SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam);
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_page_assoc
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPPAGE_GET_NAME, GetName)
+CB(API_SETUPPAGE_CREATEVIEW, CreateView)
+CB(API_SETUPPAGE_SAVE, Save)
+CB(API_SETUPPAGE_REVERT, Revert)
+CB(API_SETUPPAGE_ISDIRTY, IsDirty)
+CB(API_SETUPPAGE_VALIDATE, Validate)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_assoc.h b/Src/Winamp/setup/spage_assoc.h
new file mode 100644
index 00000000..f18270b8
--- /dev/null
+++ b/Src/Winamp/setup/spage_assoc.h
@@ -0,0 +1,57 @@
+#ifndef WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER
+#define WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER
+
+#include "./ifc_setuppage.h"
+#include <commctrl.h>
+
+#define TYPE_CATEGORIES_NUM 5
+
+class setup_page_assoc : public ifc_setuppage
+{
+public:
+ setup_page_assoc();
+ virtual ~setup_page_assoc();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText);
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void);
+ HRESULT Validate(void);
+
+protected:
+ INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam);
+ void OnDestroy(void);
+ void OnSize(UINT nType, INT cx, INT cy);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+ BOOL OnNotify(INT nCtrlID, NMHDR *pnmh, LRESULT *pResult);
+
+ BOOL TreeView_OnClick(NMHDR *pnmh);
+ void TreeView_OnItemStateClick(HWND hwndTree, HTREEITEM hItem);
+ BOOL TreeView_OnKeyDown(NMTVKEYDOWN *ptvkd);
+ INT TreeView_OnCustomDraw(NMTVCUSTOMDRAW *ptvcd);
+
+ void UpdateUI(void);
+
+private:
+ size_t ref;
+ HWND hwnd;
+ wchar_t *pszTypes;
+ WORD *pMeta;
+ BYTE expanded[TYPE_CATEGORIES_NUM];
+ wchar_t szTopExt[32];
+ wchar_t szCaretExt[32];
+ BOOL bRegCD;
+ BOOL bAgent;
+ BOOL bExplorerMenu;
+
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+};
+
+#endif //WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_connect.cpp b/Src/Winamp/setup/spage_connect.cpp
new file mode 100644
index 00000000..af0e84cc
--- /dev/null
+++ b/Src/Winamp/setup/spage_connect.cpp
@@ -0,0 +1,313 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./spage_connect.h"
+#include "./setup_resource.h"
+#include "../nu/ns_wc.h"
+#include "./langutil.h"
+
+setup_page_connect::setup_page_connect() : ref(1), hwnd(NULL)
+{
+ inetMode = 0;
+ bPort80 = FALSE;
+ szProxy[MAX_PATH] = 0x00;
+}
+setup_page_connect::~setup_page_connect()
+{
+}
+
+size_t setup_page_connect::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_page_connect::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_page_connect::GetName(bool bShort, const wchar_t **pszName)
+{
+ static wchar_t szName[64] = {0,};
+ *pszName = (*szName) ? szName : getStringW(IDS_PAGE_CONNECTIVITY, szName, sizeof(szName)/sizeof(wchar_t));
+ return S_OK;
+}
+
+HRESULT setup_page_connect::Save(HWND hwndText)
+{
+ HRESULT hr(S_OK);
+ INT count;
+ wchar_t app[MAX_PATH] = {0}, *p;
+
+ if (S_FALSE == IsDirty()) return S_OK;
+
+ count = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t));
+ if (!count) hr = S_FALSE;
+ if (S_FALSE == hr) return hr;
+
+ if (config_inet_mode != inetMode)
+ {
+ wchar_t szText[MAX_PATH] = {0};
+ config_inet_mode = (char)inetMode;
+ WritePrivateProfileStringW(app, L"inet_mode", _itow(inetMode, szText, 10), INI_FILE);
+ }
+
+ if (2 == inetMode) szProxy[0] = 0x00;
+ if (0 == *szProxy) config_proxy[0] = 0x00;
+ else
+ {
+ count = WideCharToMultiByteSZ(CP_ACP, 0, szProxy, -1, config_proxy, sizeof(config_proxy)/sizeof(char), NULL, NULL);
+ if (!count) hr = S_FALSE;
+ }
+ if (!WritePrivateProfileStringW(app, L"Proxy", szProxy, INI_FILE)) hr = S_FALSE;
+ if (bPort80 && 0x00 == *szProxy) bPort80 = FALSE;
+ p = (bPort80) ? L"1" : L"";
+ if (!WritePrivateProfileStringW(app, L"proxyonly80", p, INI_FILE)) hr = S_FALSE;
+ WritePrivateProfileStringW(app, L"proxy80", p, INI_FILE); // old
+
+ if (hwnd) UpdateUI();
+ return hr;
+}
+
+HRESULT setup_page_connect::Revert(void)
+{
+ HRESULT hr(S_OK);
+ INT count;
+ wchar_t app[MAX_PATH] = {0};
+
+ count = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t));
+ if (!count) hr = S_FALSE;
+
+ if (config_inet_mode==3) isInetAvailable(); // autodetect
+ inetMode = config_inet_mode;
+
+ if (*config_proxy && 2 != inetMode)
+ {
+ count = MultiByteToWideCharSZ(CP_ACP, 0, config_proxy, -1, szProxy, sizeof(szProxy)/sizeof(wchar_t));
+ if (!count) hr = S_FALSE;
+ }
+ else szProxy[0] = 0x00;
+
+ bPort80 = (0x00 != *szProxy && 0 != GetPrivateProfileIntW(app, L"proxyonly80", 0, INI_FILE));
+
+ if (hwnd) UpdateUI();
+
+ return hr;
+}
+
+HRESULT setup_page_connect::IsDirty(void)
+{
+ INT res;
+ wchar_t app[MAX_PATH] = {0};
+ char szTest[MAX_PATH] = {0};
+
+ if (inetMode != config_inet_mode) return S_OK;
+
+ if (2 == inetMode || 0 == *szProxy) szTest[0] = 0x00;
+ else
+ {
+ res = WideCharToMultiByteSZ(CP_ACP, 0, szProxy, -1, szTest, sizeof(szTest)/sizeof(char), NULL, NULL);
+ if (!res) return E_OUTOFMEMORY;
+ }
+
+ res = CompareStringA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+ NORM_IGNORECASE, szTest, -1, config_proxy, -1);
+ if (0 == res) return E_UNEXPECTED;
+ if (CSTR_EQUAL != res) return S_OK;
+
+ res = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t));
+ if (!res) return E_OUTOFMEMORY;
+
+ return ((bPort80 && 0x00 != *szProxy) != ( 0 != GetPrivateProfileIntW(app, L"proxyonly80", 0, INI_FILE))) ? S_OK : S_FALSE;
+}
+
+HRESULT setup_page_connect::Validate(void)
+{
+ return S_OK;
+}
+
+HRESULT setup_page_connect::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_CONNECT), hwndParent, ::DialogProc, (LPARAM)this);
+ return S_OK;
+}
+
+void setup_page_connect::UpdateUI(void)
+{
+ int count;
+
+ if (!hwnd || !IsWindow(hwnd)) return;
+
+ CheckDlgButton(hwnd, IDC_CHK_PORT80, (bPort80) ? BST_CHECKED : BST_UNCHECKED);
+ SetDlgItemTextW(hwnd, IDC_EDT_SERVER, szProxy);
+
+ HWND hwndCB = GetDlgItem(hwnd, IDC_CB_CONNECT);
+ if (!hwndCB || !IsWindow(hwndCB)) return;
+
+ count = (INT)SendMessageW(hwndCB, CB_GETCOUNT, 0, 0L);
+ if (count > 0)
+ {
+ int index;
+ for (index = 0; index < count && inetMode != (INT)SendMessageW(hwndCB, CB_GETITEMDATA, index, 0L); index++);
+ if (index == count)
+ {
+ inetMode = (INT)SendMessageW(hwndCB, CB_GETITEMDATA, 0, 0L);
+ index = 0;
+ }
+ SendMessageW(hwndCB, CB_SETCURSEL, index, 0L);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CB_CONNECT, CBN_SELCHANGE), (LPARAM)hwndCB);
+ }
+}
+
+void setup_page_connect::ComboBox_OnSelChange(HWND hwndCtrl)
+{
+ INT proxyList[] = { IDC_GRP_PROXY, IDC_LBL_SERVER, IDC_EDT_SERVER, IDC_CHK_PORT80, };
+ INT index;
+
+ index = (INT)SendMessageW(hwndCtrl, CB_GETCURSEL, 0, 0L);
+ if (CB_ERR == index) return;
+
+ inetMode = (INT)SendMessageW(hwndCtrl, CB_GETITEMDATA, index, 0L);
+
+ for (int i = 0; i < sizeof(proxyList)/sizeof(INT); i++)
+ {
+ HWND hwndItem = GetDlgItem(hwnd, proxyList[i]);
+ if (IsWindow(hwndItem)) ShowWindow(hwndItem, (2 != inetMode) ? SW_SHOWNA : SW_HIDE);
+ }
+}
+
+INT_PTR setup_page_connect::OnInitDialog(HWND hwndFocus, LPARAM lParam)
+{
+ UINT connID[] = { IDS_INST_INET1, IDS_INST_INET2, IDS_INST_INET3, };
+ HWND hwndCB = GetDlgItem(hwnd, IDC_CB_CONNECT);
+
+ CheckDlgButton(hwnd, IDC_CHK_PORT80, (bPort80) ? BST_CHECKED : BST_UNCHECKED);
+ //SendDlgItemMessageW(hwnd, IDC_EDT_SERVER, EM_LIMITTEXT, sizeof(szProxy)/sizeof(wchar_t), 0);
+ SetDlgItemTextW(hwnd, IDC_EDT_SERVER, szProxy);
+
+ if (inetMode < 0) inetMode = 0;
+ else if (inetMode >= sizeof(connID)/sizeof(INT)) inetMode = sizeof(connID)/sizeof(INT) - 1;
+
+ for(int i = 0; i < sizeof(connID)/sizeof(INT); i++)
+ {
+ INT index = (INT)SendMessageW(hwndCB, CB_ADDSTRING,0, (LPARAM)getStringW(connID[i], NULL, 0));
+ if (CB_ERR != index) SendMessageW(hwndCB, CB_SETITEMDATA, index, (LPARAM)i);
+ if (inetMode == i) SendMessageW(hwndCB, CB_SETCURSEL, index, 0L);
+ }
+
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CB_CONNECT, CBN_SELCHANGE), (LPARAM)hwndCB);
+
+ return 0;
+}
+
+void setup_page_connect::OnSize(UINT nType, INT cx, INT cy)
+{
+ INT ctrlList[] = { IDC_CB_CONNECT, IDC_GRP_PROXY, IDC_LBL_SERVER, IDC_EDT_SERVER, IDC_CHK_PORT80, };
+ RECT rw;
+ HDWP hdwp = BeginDeferWindowPos(sizeof(ctrlList)/sizeof(INT));
+ if (!hdwp) return;
+
+ for (int i = 0; i < sizeof(ctrlList)/sizeof(INT); i++)
+ {
+ HWND hwndCtrl = GetDlgItem(hwnd, ctrlList[i]);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ hdwp = DeferWindowPos(hdwp, hwndCtrl, NULL, max(0, (cx - (rw.right - rw.left))/2), rw.top, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+ }
+ }
+ if (hdwp) EndDeferWindowPos(hdwp);
+}
+
+void setup_page_connect::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDC_CB_CONNECT:
+ switch(nEvntID)
+ {
+ case CBN_SELCHANGE: ComboBox_OnSelChange(hwndCtrl); break;
+ }
+ break;
+ case IDC_EDT_SERVER:
+ switch(nEvntID)
+ {
+ case EN_CHANGE:
+ GetWindowTextW(hwndCtrl, szProxy, sizeof(szProxy)/sizeof(wchar_t));
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_PORT80), 0x00 != *szProxy);
+ if(0x00 == *szProxy)
+ {
+ CheckDlgButton(hwnd, IDC_CHK_PORT80, BST_UNCHECKED);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CHK_PORT80, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_CHK_PORT80));
+ }
+ break;
+ }
+ break;
+ case IDC_CHK_PORT80:
+ switch(nEvntID)
+ {
+ case BN_CLICKED: bPort80 = (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)); break;
+ }
+ break;
+ }
+}
+
+INT_PTR setup_page_connect::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: break;
+ case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break;
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ }
+ return 0;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ setup_page_connect *pInst = (setup_page_connect*)GetPropW(hwnd, L"SETUPPAGE");
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ pInst = (setup_page_connect*)lParam;
+ if (pInst)
+ {
+ pInst->hwnd = hwnd;
+ SetPropW(hwnd, L"SETUPPAGE", pInst);
+ }
+ break;
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->PageDlgProc(uMsg, wParam, lParam);
+ RemovePropW(hwnd, L"SETUPPAGE");
+ pInst = NULL;
+ }
+ break;
+ }
+ return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_page_connect
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPPAGE_GET_NAME, GetName)
+CB(API_SETUPPAGE_CREATEVIEW, CreateView)
+CB(API_SETUPPAGE_SAVE, Save)
+CB(API_SETUPPAGE_REVERT, Revert)
+CB(API_SETUPPAGE_ISDIRTY, IsDirty)
+CB(API_SETUPPAGE_VALIDATE, Validate)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_connect.h b/Src/Winamp/setup/spage_connect.h
new file mode 100644
index 00000000..c4af10d7
--- /dev/null
+++ b/Src/Winamp/setup/spage_connect.h
@@ -0,0 +1,45 @@
+#ifndef WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER
+#define WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER
+
+#include "./ifc_setuppage.h"
+
+class setup_page_connect : public ifc_setuppage
+{
+
+public:
+ setup_page_connect();
+ virtual ~setup_page_connect();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText);
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void);
+ HRESULT Validate(void);
+protected:
+ INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam);
+ void OnSize(UINT nType, INT cx, INT cy);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+
+ void ComboBox_OnSelChange(HWND hwndCtrl);
+
+ void UpdateUI(void);
+
+private:
+ size_t ref;
+ HWND hwnd;
+ INT inetMode;
+ BOOL bPort80;
+ WCHAR szProxy[MAX_PATH];
+
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+};
+
+
+#endif //WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_feedback.cpp b/Src/Winamp/setup/spage_feedback.cpp
new file mode 100644
index 00000000..4a2515e4
--- /dev/null
+++ b/Src/Winamp/setup/spage_feedback.cpp
@@ -0,0 +1,392 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./spage_feedback.h"
+#include "./setup_resource.h"
+#include "../nu/ns_wc.h"
+#include "../nu/AutoChar.h"
+#include "../nu/AutoWide.h"
+#include "./langutil.h"
+
+
+#define FF_ALLOWFEEDBACK 0x0001
+#define FF_ANNOUNCEMENTS 0x0010
+#define FF_STATISTICS 0x0020
+
+#define GENDER_UNKNOWN 0
+#define GENDER_MALE 1
+#define GENDER_FEMALE 2
+
+setup_page_feedback::setup_page_feedback() : ref(1), hwnd(NULL)
+{
+ szEmail[0] = 0x00;
+ szCountry[0] = 0x00;
+ gender = GENDER_UNKNOWN;
+ flags = FF_ALLOWFEEDBACK | FF_ANNOUNCEMENTS | FF_STATISTICS;
+}
+
+setup_page_feedback::~setup_page_feedback()
+{
+}
+
+size_t setup_page_feedback::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_page_feedback::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_page_feedback::GetName(bool bShort, const wchar_t **pszName)
+{
+ if (bShort)
+ {
+ static wchar_t szShortName[32] = {0};
+ *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_FEEDBACK, szShortName, sizeof(szShortName)/sizeof(wchar_t));
+ }
+ else
+ {
+ static wchar_t szLongName[64] = {0};
+ *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_FEEDBACK_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t));
+ }
+ return S_OK;
+}
+
+HRESULT setup_page_feedback::Save(HWND hwndText)
+{
+ HRESULT hr(S_OK);
+
+ int r, s;
+ char data[8192] = {0};
+ char str[32] = {0};
+
+ if (FF_ALLOWFEEDBACK & flags)
+ {
+ s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE);
+ if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA);
+ if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, -1)) hr = E_UNEXPECTED;
+ if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szCountry, lstrlenW(szCountry)*sizeof(wchar_t))) hr = E_UNEXPECTED;
+ if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &gender, sizeof(gender))) hr = E_UNEXPECTED;
+ r = (FF_ANNOUNCEMENTS == (FF_ANNOUNCEMENTS & flags));
+ if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &r, sizeof(r))) hr = E_UNEXPECTED;
+ config_newverchk2 = (FF_STATISTICS == (FF_STATISTICS & flags));
+ }
+ else config_newverchk2 = 0;
+
+ WritePrivateProfileStringW(AutoWide(app_name), L"newverchk2", (config_newverchk2) ? L"1" : L"0", INI_FILE);
+
+ s = GetMetricsSize(data);
+
+ StringCchPrintfA(str, 32, "%d", s);
+ WritePrivateProfileStringA("WinampReg", "RegDataLen", (s) ? str : NULL, INI_FILEA);
+ WritePrivateProfileStructA("WinampReg", "RegData2", (s) ? data : NULL, s, INI_FILEA);
+
+ if (hwnd) UpdateUI();
+ return hr;
+}
+
+HRESULT setup_page_feedback::Revert(void)
+{
+ HRESULT hr(S_OK);
+ char data[8192] = {0, };
+ DWORD sendinfo;
+
+ flags = FF_ALLOWFEEDBACK;
+
+ if (config_newverchk2) flags |= FF_STATISTICS;
+
+ int s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE);
+ if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA);
+
+ GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, sizeof(szEmail));
+ GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szCountry, sizeof(szCountry));
+ GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &gender, sizeof(gender));
+ GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &sendinfo, sizeof(sendinfo));
+ if (sendinfo) flags |= FF_ANNOUNCEMENTS;
+ if (hwnd) UpdateUI();
+ return hr;
+}
+
+HRESULT setup_page_feedback::IsDirty(void)
+{
+ char data[8192] = {0};
+ wchar_t szTest[256] = {0};
+ int r;
+ DWORD lcid;
+
+ lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ if (0 != (FF_STATISTICS & flags) != !!config_newverchk2) return S_OK;
+
+ int s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE);
+ if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA);
+
+ if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szTest, sizeof(szTest))) return E_UNEXPECTED;
+ r = CompareStringW(lcid, NORM_IGNORECASE, szTest, -1, szEmail, -1);
+ if (0 == r) return E_UNEXPECTED;
+ if (CSTR_EQUAL != r) return S_OK;
+
+ if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szTest, sizeof(szTest))) return E_UNEXPECTED;
+ r = CompareStringW(lcid, NORM_IGNORECASE, szTest, -1, szCountry, -1);
+ if (0 == r) return E_UNEXPECTED;
+ if (CSTR_EQUAL != r) return S_OK;
+ r = 0;
+ if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &r, sizeof(r))) return E_UNEXPECTED;
+ if (r != gender) return S_OK;
+ r = 0;
+ if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &r, sizeof(r))) return E_UNEXPECTED;
+ if (r != (FF_ANNOUNCEMENTS == (FF_ANNOUNCEMENTS & flags))) return S_OK;
+
+ return S_FALSE;
+}
+
+HRESULT setup_page_feedback::Validate(void)
+{
+ wchar_t *p;
+
+ if (0 == (FF_ALLOWFEEDBACK & flags) || !*szEmail) return S_OK;
+ for (p = szEmail; *p != 0x00 && *p != L'@'; p = CharNextW(p));
+
+ if (L'@' != *p || 0x00 == *CharNextW(p))
+ {
+ WCHAR szTitle[128] = {0};
+ HWND hwndTop, hwndTest;
+ hwndTop = hwnd;
+ while(NULL != (hwndTest = GetParent(hwndTop))) hwndTop = hwndTest;
+ GetWindowTextW(hwndTop, szTitle, sizeof(szTitle)/sizeof(WCHAR));
+ if (hwndTop)
+ {
+ MessageBoxW(hwndTop, getStringW(IDS_PAGE_INCORRECT_EMAIL_ADDRESS, NULL, 0),
+ szTitle, MB_OK | MB_ICONERROR);
+ return S_FALSE;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT setup_page_feedback::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_FEEDBACK), hwndParent, ::DialogProc, (LPARAM)this);
+ return S_OK;
+}
+
+void setup_page_feedback::UpdateUI(void)
+{
+
+ HWND hwndCB;
+ if (!hwnd || !IsWindow(hwnd)) return;
+
+ CheckDlgButton(hwnd, IDC_CHK_ANNOUNCEMENTS, (FF_ANNOUNCEMENTS & flags) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_STATISTICS, (FF_STATISTICS & flags) ? BST_CHECKED : BST_UNCHECKED);
+
+ SetDlgItemTextW(hwnd, IDC_EDT_EMAIL, szEmail);
+ SetDlgItemTextW(hwnd, IDC_EDT_COUNTRY, szCountry);
+
+ hwndCB = GetDlgItem(hwnd, IDC_CB_GENDER);
+ if (hwndCB)
+ {
+ INT count = (INT)SendMessageW(hwndCB, CB_GETCOUNT, 0, 0L);
+ if (count > 0)
+ {
+ INT i;
+ for (i = 0; i < count && gender != (INT)SendMessageW(hwndCB, CB_GETITEMDATA, i, 0L); i++);
+ if (i != count) SendMessageW(hwndCB, CB_SETCURSEL, i, 0L);
+ }
+ }
+}
+
+
+void setup_page_feedback::ComboBox_OnSelChange(HWND hwndCtrl)
+{
+ INT index;
+ index = (INT)SendMessageW(hwndCtrl, CB_GETCURSEL, 0, 0L);
+ if (CB_ERR == index) return;
+ gender = (INT)SendMessageW(hwndCtrl, CB_GETITEMDATA, index, 0L);
+}
+
+INT_PTR setup_page_feedback::OnInitDialog(HWND hwndFocus, LPARAM lParam)
+{
+ HWND hwndCB;
+
+ SendDlgItemMessageW(hwnd, IDC_EDT_EMAIL, EM_LIMITTEXT, sizeof(szEmail)/sizeof(wchar_t), 0);
+ SendDlgItemMessageW(hwnd, IDC_EDT_COUNTRY, EM_LIMITTEXT, sizeof(szCountry)/sizeof(wchar_t), 0);
+
+ hwndCB = GetDlgItem(hwnd, IDC_CB_GENDER);
+ if (hwndCB)
+ {
+ UINT genderStrID[] = {IDS_GENDER_UNKNOWN, IDS_GENDER_FEMALE, IDS_GENDER_MALE, };
+ INT genderVal[] = {GENDER_UNKNOWN, GENDER_FEMALE, GENDER_MALE, };
+ for(int i = 0; i < sizeof(genderStrID)/sizeof(UINT); i++)
+ {
+ INT index = (INT)SendMessageW(hwndCB, CB_ADDSTRING,0, (LPARAM)getStringW(genderStrID[i], NULL, 0));
+ if (CB_ERR != index) SendMessageW(hwndCB, CB_SETITEMDATA, index, (LPARAM)genderVal[i]);
+ }
+ }
+
+ UpdateUI();
+ return 0;
+}
+
+void setup_page_feedback::OnSize(UINT nType, INT cx, INT cy)
+{
+ INT ctrlList[] = { IDC_LBL_HEADER, IDC_CHK_ANNOUNCEMENTS, IDC_CHK_STATISTICS,
+ IDC_EDT_EMAIL, IDC_EDT_COUNTRY, IDC_CB_GENDER, };
+ HWND hwndCtrl;
+ HDWP hdwp;
+ RECT rw;
+ INT width, ox;
+
+ hwndCtrl = GetDlgItem(hwnd, IDC_LBL_EMAIL);
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ ox = rw.left;
+
+ hdwp = BeginDeferWindowPos(sizeof(ctrlList)/sizeof(INT));
+ if (!hdwp) return;
+
+ for (int i = 0; i < sizeof(ctrlList)/sizeof(INT); i++)
+ {
+ hwndCtrl = GetDlgItem(hwnd, ctrlList[i]);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ switch(ctrlList[i])
+ {
+ case IDC_EDT_EMAIL:
+ case IDC_EDT_COUNTRY:
+ case IDC_CB_GENDER:
+ width = cx - rw.left - ox;
+ break;
+ default:
+ width = cx - rw.left*2;
+ break;
+ }
+ hdwp = DeferWindowPos(hdwp, hwndCtrl, NULL, 0, 0, width, rw.bottom - rw.top,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
+ }
+ }
+ if (hdwp) EndDeferWindowPos(hdwp);
+}
+
+
+void setup_page_feedback::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDC_EDT_EMAIL:
+ switch(nEvntID)
+ {
+ case EN_CHANGE:
+ {
+ GetWindowTextW(hwndCtrl, szEmail, sizeof(szEmail)/sizeof(wchar_t));
+ HWND hwndChk = GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS);
+ if (IsWindow(hwndChk))
+ {
+ BOOL bEnabled = IsWindowEnabled(hwndChk);
+ if (bEnabled != (0x00 != *szEmail))
+ {
+ CheckDlgButton(hwnd, IDC_CHK_ANNOUNCEMENTS, (0x00 != *szEmail) ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS), 0x00 != *szEmail);
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CHK_ANNOUNCEMENTS, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS));
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case IDC_EDT_COUNTRY:
+ switch(nEvntID)
+ {
+ case EN_CHANGE:
+ GetWindowTextW(hwndCtrl, szCountry, sizeof(szCountry)/sizeof(wchar_t));
+ break;
+ }
+ break;
+ case IDC_CHK_ANNOUNCEMENTS:
+ switch(nEvntID)
+ {
+ case BN_CLICKED:
+ if (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)) flags |= FF_ANNOUNCEMENTS;
+ else flags &= ~FF_ANNOUNCEMENTS;
+ break;
+ }
+ break;
+ case IDC_CHK_STATISTICS:
+ switch(nEvntID)
+ {
+ case BN_CLICKED:
+ if (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)) flags |= FF_STATISTICS;
+ else flags &= ~FF_STATISTICS;
+ break;
+ }
+ break;
+ case IDC_CB_GENDER:
+ switch(nEvntID)
+ {
+ case CBN_SELCHANGE: ComboBox_OnSelChange(hwndCtrl); break;
+ }
+ break;
+ }
+}
+
+INT_PTR setup_page_feedback::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: break;
+ case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break;
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ }
+ return 0;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ setup_page_feedback *pInst = (setup_page_feedback*)GetPropW(hwnd, L"SETUPPAGE");
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ pInst = (setup_page_feedback*)lParam;
+ if (pInst)
+ {
+ pInst->hwnd = hwnd;
+ SetPropW(hwnd, L"SETUPPAGE", pInst);
+ }
+ break;
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->PageDlgProc(uMsg, wParam, lParam);
+ RemovePropW(hwnd, L"SETUPPAGE");
+ pInst = NULL;
+ }
+ break;
+ }
+
+ return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_page_feedback
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPPAGE_GET_NAME, GetName)
+CB(API_SETUPPAGE_CREATEVIEW, CreateView)
+CB(API_SETUPPAGE_SAVE, Save)
+CB(API_SETUPPAGE_REVERT, Revert)
+CB(API_SETUPPAGE_ISDIRTY, IsDirty)
+CB(API_SETUPPAGE_VALIDATE, Validate)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_feedback.h b/Src/Winamp/setup/spage_feedback.h
new file mode 100644
index 00000000..1ce53c13
--- /dev/null
+++ b/Src/Winamp/setup/spage_feedback.h
@@ -0,0 +1,45 @@
+#ifndef WINAMP_FEEDBACK_SETUP_PAGE_HEADER
+#define WINAMP_FEEDBACK_SETUP_PAGE_HEADER
+
+#include "./ifc_setuppage.h"
+
+class setup_page_feedback : public ifc_setuppage
+{
+
+public:
+ setup_page_feedback();
+ virtual ~setup_page_feedback();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText);
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void);
+ HRESULT Validate(void);
+protected:
+ INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam);
+ void OnSize(UINT nType, INT cx, INT cy);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+
+ void ComboBox_OnSelChange(HWND hwndCtrl);
+ void UpdateUI(void);
+
+private:
+ size_t ref;
+ HWND hwnd;
+ WCHAR szEmail[MAX_PATH];
+ WCHAR szCountry[MAX_PATH];
+ INT gender;
+ DWORD flags;
+
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+};
+
+
+#endif //WINAMP_FEEDBACK_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_lang.cpp b/Src/Winamp/setup/spage_lang.cpp
new file mode 100644
index 00000000..83282311
--- /dev/null
+++ b/Src/Winamp/setup/spage_lang.cpp
@@ -0,0 +1,293 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./spage_lang.h"
+#include "./setup_resource.h"
+#include "../nu/ns_wc.h"
+#include "./langutil.h"
+
+typedef struct _LANGREC
+{
+ LPWSTR pszFileName;
+ INT nType;
+} LANGREC;
+
+
+static BOOL CALLBACK AddLangToListBox(ENUMLANG *pel, LPVOID pUser);
+static INT ListBox_FindLangFileIndex(HWND hwndLB, LPCWSTR pszLangPath);
+static LPCWSTR ListBox_GetSelectedLang(HWND hwndLB, LPWSTR pszLangPath, INT cchLen);
+
+
+setup_page_lang::setup_page_lang() : ref(1), hwnd(NULL)
+{
+ *szSelectionPath = 0x00;
+}
+setup_page_lang::~setup_page_lang()
+{
+}
+
+size_t setup_page_lang::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_page_lang::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_page_lang::GetName(bool bShort, const wchar_t **pszName)
+{
+ static wchar_t szName[64] = {0};
+ *pszName = (*szName) ? szName : getStringW(IDS_PAGE_LANGUAGE, szName, sizeof(szName)/sizeof(wchar_t));
+ return S_OK;
+}
+
+HRESULT setup_page_lang::Save(HWND hwndText)
+{
+ if (S_FALSE == IsDirty()) return S_OK;
+
+ if (!*szSelectionPath) *config_langpack = 0x00;
+ else
+ {
+ StringCbCopyW(config_langpack, sizeof(config_langpack), szSelectionPath);
+ }
+ config_save_langpack_var();
+ return S_OK;
+}
+
+HRESULT setup_page_lang::Revert(void)
+{
+ HRESULT hr(S_OK);
+
+ if (*config_langpack)
+ {
+ StringCbCopyW(config_langpack, sizeof(szSelectionPath), config_langpack);
+ }
+ else szSelectionPath[0] = 0x00;
+
+ if (hwnd)
+ {
+ HWND hwndLB = GetDlgItem(hwnd, IDC_LB_LANG);
+ INT index = ListBox_FindLangFileIndex(hwndLB, szSelectionPath);
+ if (LB_ERR == index && *szSelectionPath) index = ListBox_FindLangFileIndex(hwndLB, NULL); // find default embeded lang
+ SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L);
+ }
+ return hr;
+}
+
+HRESULT setup_page_lang::IsDirty(void)
+{
+ INT cr;
+
+ cr = ComparePath(config_langpack, szSelectionPath, LANGDIR);
+ if (!cr) return E_UNEXPECTED;
+
+ return (CSTR_EQUAL != cr) ? S_OK : S_FALSE;
+}
+
+HRESULT setup_page_lang::Validate(void)
+{
+ return S_OK;
+}
+
+HRESULT setup_page_lang::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_LANG), hwndParent, ::DialogProc, (LPARAM)this);
+ return S_OK;
+}
+
+void setup_page_lang::ListBox_OnSelChange(HWND hwndCtrl)
+{
+ ListBox_GetSelectedLang(hwndCtrl, szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t));
+}
+
+void setup_page_lang::ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis)
+{
+ LANGREC *pr = (LANGREC*)pdis->itemData;
+ if (pr)
+ {
+ if (pr->pszFileName) free(pr->pszFileName);
+ free(pr);
+ }
+}
+
+INT_PTR setup_page_lang::OnInitDialog(HWND hwndFocus, LPARAM lParam)
+{
+ INT index;
+ HWND hwndLB;
+ hwndLB = GetDlgItem(hwnd, IDC_LB_LANG);
+ EnumerateLanguages(AddLangToListBox, hwndLB);
+ index = ListBox_FindLangFileIndex(hwndLB, szSelectionPath);
+ if (LB_ERR == index && *szSelectionPath) index = ListBox_FindLangFileIndex(hwndLB, NULL); // find default embeded lang
+ SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L);
+
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_LANG, LBN_SELCHANGE), (LPARAM)hwndLB);
+ return 0;
+}
+
+void setup_page_lang::OnSize(UINT nType, INT cx, INT cy)
+{
+ HWND hwndCtrl;
+ RECT rw;
+
+ hwndCtrl = GetDlgItem(hwnd, IDC_LBL_HEADER);
+ if (hwndCtrl)
+ {
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, 0, 0, cx - rw.left*2, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
+ }
+ hwndCtrl = GetDlgItem(hwnd, IDC_LB_LANG);
+ if (hwndCtrl)
+ {
+
+ GetWindowRect(hwndCtrl, &rw);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2);
+ SetWindowPos(hwndCtrl, NULL, max(0, (cx - (rw.right - rw.left))/2), rw.top, rw.right - rw.left, cy - rw.top - 16, SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+}
+
+void setup_page_lang::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_LANG:
+ switch(nEvntID)
+ {
+ case LBN_SELCHANGE: ListBox_OnSelChange(hwndCtrl); break;
+ }
+ break;
+ }
+}
+
+INT_PTR setup_page_lang::OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_LANG: ListBox_OnItemDelete(pdis); return TRUE;
+ }
+ return 0;
+}
+
+INT_PTR setup_page_lang::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: break;
+ case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break;
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ }
+ return 0;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ setup_page_lang *pInst = (setup_page_lang*)GetPropW(hwnd, L"SETUPPAGE");
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ pInst = (setup_page_lang*)lParam;
+ if (pInst)
+ {
+ pInst->hwnd = hwnd;
+ SetPropW(hwnd, L"SETUPPAGE", pInst);
+ }
+ break;
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->PageDlgProc(uMsg, wParam, lParam);
+ RemovePropW(hwnd, L"SETUPPAGE");
+ pInst = NULL;
+ }
+ break;
+ }
+
+ return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
+}
+
+static BOOL CALLBACK AddLangToListBox(ENUMLANG *pel, LPVOID pUser)
+{
+ INT index;
+ LANGREC *pr;
+ HWND hwndLB = (HWND)pUser;
+ if (!hwndLB) return FALSE;
+
+ pr = (LANGREC*)calloc(1, sizeof(LANGREC));
+ if (!pr) return FALSE;
+ pr->nType = pel->nType;
+ if (pel->pszFileName) pr->pszFileName = _wcsdup(pel->pszFileName);
+
+ index = (INT)SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)pel->pszName);
+ if (LB_ERR != index) SendMessageW(hwndLB, LB_SETITEMDATA, index, (LPARAM)pr);
+ else
+ {
+ if (pr->pszFileName) free(pr->pszFileName);
+ free(pr);
+ }
+ return TRUE;
+}
+
+static INT ListBox_FindLangFileIndex(HWND hwndLB, LPCWSTR pszLangPath)
+{
+ int index, count;
+
+ if (!hwndLB) return LB_ERR;
+
+ index = LB_ERR;
+
+ count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L);
+ for (index = 0; index < count; index++)
+ {
+ LANGREC *pr = (LANGREC*) SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L);
+ if (!pr || LB_ERR == (INT)(INT_PTR)pr) continue;
+ if (!pszLangPath || !*pszLangPath)
+ {
+ if (LANG_FILETYPE_EMBED == pr->nType && (!pr->pszFileName || !*pr->pszFileName)) break;
+ }
+ else
+ {
+ if (CSTR_EQUAL == ComparePath(pszLangPath, pr->pszFileName, LANGDIR)) break;
+ }
+ }
+ return (count == index) ? LB_ERR : index;
+}
+
+static LPCWSTR ListBox_GetSelectedLang(HWND hwndLB, LPWSTR pszLangPath, INT cchLen)
+{
+ INT index;
+ LANGREC *pr;
+ if (!hwndLB || !pszLangPath) return NULL;
+ index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L);
+ if (LB_ERR == index) return NULL;
+ pr = (LANGREC*)SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L);
+ if (!pr || LB_ERR == (INT)(INT_PTR)pr) return NULL;
+
+ if (!pr->pszFileName || !*pr->pszFileName) pszLangPath[0] = 0x00;
+ else if (S_OK != StringCchCopyW(pszLangPath, cchLen, pr->pszFileName)) return NULL;
+ return pszLangPath;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_page_lang
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPPAGE_GET_NAME, GetName)
+CB(API_SETUPPAGE_CREATEVIEW, CreateView)
+CB(API_SETUPPAGE_SAVE, Save)
+CB(API_SETUPPAGE_REVERT, Revert)
+CB(API_SETUPPAGE_ISDIRTY, IsDirty)
+CB(API_SETUPPAGE_VALIDATE, Validate)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_lang.h b/Src/Winamp/setup/spage_lang.h
new file mode 100644
index 00000000..f3848ab7
--- /dev/null
+++ b/Src/Winamp/setup/spage_lang.h
@@ -0,0 +1,42 @@
+#ifndef WINAMP_LANGUAGE_SETUP_PAGE_HEADER
+#define WINAMP_LANGUAGE_SETUP_PAGE_HEADER
+
+#include "./ifc_setuppage.h"
+
+class setup_page_lang : public ifc_setuppage
+{
+
+public:
+ setup_page_lang();
+ virtual ~setup_page_lang();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText);
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void);
+ HRESULT Validate(void);
+protected:
+ INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam);
+ void OnSize(UINT nType, INT cx, INT cy);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+ INT_PTR OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis);
+ void ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis);
+ void ListBox_OnSelChange(HWND hwndCtrl);
+
+private:
+ size_t ref;
+ HWND hwnd;
+ wchar_t szSelectionPath[MAX_PATH];
+
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+};
+
+
+#endif //WINAMP_LANGUAGE_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_skin.cpp b/Src/Winamp/setup/spage_skin.cpp
new file mode 100644
index 00000000..d50f3998
--- /dev/null
+++ b/Src/Winamp/setup/spage_skin.cpp
@@ -0,0 +1,646 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "main.h"
+#include "./spage_skin.h"
+#include "./setup_resource.h"
+#include "./skininfo.h"
+#include "../nu/ns_wc.h"
+#include "../nu/AutoWide.h"
+#include "./loadimage.h"
+#include "./langutil.h"
+#include "./setupcommon.h"
+
+typedef struct _SKINLINK
+{
+ LPCWSTR pszName;
+ LPCWSTR pszTarget;
+} SKINLINK;
+
+typedef struct _SKINREC
+{
+ LPWSTR pszName;
+ LPWSTR pszFileName;
+ INT nType;
+ BOOL bLink; // if bLink == TRUE than nType index in links
+} SKINREC;
+
+#define CURRENT_SKIN_ID 1
+#define SEPARATOR_DATA 0xEFFF
+
+#define LINK_FONT_ITALIC FALSE
+#define LINK_FONT_WEIGHT FW_MEDIUM
+//#define LINK_TEXT_COLOR RGB(0, 50, 193)
+//#define LINK_TEXT_HIGHLITECOLOR RGB(16, 64, 212)
+
+#define PREVIEW_WIDTH 178
+#define PREVIEW_HEIGHT 75
+
+static SKINLINK links[] =
+{
+ { MAKEINTRESOURCEW(IDS_SKIN_PROMO1), BENTO_SKIN_NAME },
+ { MAKEINTRESOURCEW(IDS_SKIN_PROMO2), BIG_BENTO_SKIN_NAME },
+ { MAKEINTRESOURCEW(IDS_SKIN_CURRENT), MAKEINTRESOURCEW(CURRENT_SKIN_ID) },
+};
+
+static wchar_t szClassic[64] = {0, };
+
+#define CLASSIC_NAME() ((!*szClassic) ? getStringW(IDS_CLASSIC_SKIN_NAME, szClassic, sizeof(szClassic)/sizeof(wchar_t)) : szClassic)
+
+static BOOL CALLBACK AddSkinToListBox(ENUMSKIN *pes, LPVOID pUser);
+static LRESULT WINAPI ListBoxProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LPCWSTR ResolveLink(SKINREC *pr);
+static INT ListBox_FindSkinFileIndex(HWND hwndLB, LPCWSTR pszSkinPath, BOOL bSearchLinks);
+
+setup_page_skin::setup_page_skin() : ref(1), hwnd(NULL), hfLink(NULL), idxSelected(-1)
+{
+ *szSelectionPath = 0x00;
+}
+
+setup_page_skin::~setup_page_skin()
+{
+}
+
+size_t setup_page_skin::AddRef()
+{
+ return ++ref;
+}
+
+size_t setup_page_skin::Release()
+{
+ if (1 == ref)
+ {
+ delete(this);
+ return 0;
+ }
+ return --ref;
+}
+
+HRESULT setup_page_skin::GetName(bool bShort, const wchar_t **pszName)
+{
+ if (bShort)
+ {
+ static wchar_t szShortName[32] = {0};
+ *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_SKIN, szShortName, sizeof(szShortName)/sizeof(wchar_t));
+ }
+ else
+ {
+ static wchar_t szLongName[64] = {0};
+ *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_SKIN_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t));
+ }
+ return S_OK;
+}
+
+HRESULT setup_page_skin::Save(HWND hwndText)
+{
+ if (S_FALSE == IsDirty()) return S_OK;
+
+ if (!*szSelectionPath) *config_skin = 0x00;
+ else if (S_OK != StringCchCopyW(config_skin, sizeof(config_skin)/sizeof(wchar_t), szSelectionPath)) return S_FALSE;
+
+ _w_sW("skin", config_skin);
+ if (hwnd)
+ {
+ HWND hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN);
+ INT index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE);
+ if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded skin
+ SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L);
+ }
+ return S_OK;//(count) ? S_OK : S_FALSE;
+}
+
+static BOOL IsForceBento()
+{
+ wchar_t szVer[128] = {0};
+ if (GetPrivateProfileIntW(L"WinampReg", L"IsFirstInst", 0, INI_FILE)) return TRUE;
+ GetPrivateProfileStringW(L"WinampReg", L"WAVer", L"", szVer, 128, INI_FILE);
+ return (!*szVer || CSTR_LESS_THAN == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
+ NORM_IGNORECASE, szVer, -1, AutoWide(APP_VERSION), -1));
+}
+
+HRESULT setup_page_skin::Revert(void)
+{
+ HRESULT hr(S_OK);
+
+ if (NULL != config_skin && !IsForceBento()) StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), config_skin);
+ else StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), L"Bento");
+
+ if (hwnd)
+ {
+ HWND hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN);
+ INT index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE);
+ if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded skin
+ SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L);
+ }
+ return hr;
+}
+
+HRESULT setup_page_skin::IsDirty(void)
+{
+ INT cr;
+
+ if (IsForceBento()) return S_OK;
+
+ cr = ComparePath(config_skin, szSelectionPath, SKINDIR);
+ if (!cr) return E_UNEXPECTED;
+ return (CSTR_EQUAL != cr) ? S_OK : S_FALSE;
+}
+
+HRESULT setup_page_skin::Validate(void)
+{
+ return S_OK;
+}
+
+HRESULT setup_page_skin::CreateView(HWND hwndParent, HWND *phwnd)
+{
+ *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_SKIN), hwndParent, ::DialogProc, (LPARAM)this);
+ return S_OK;
+}
+
+void setup_page_skin::ListBox_OnSelChange(HWND hwndCtrl)
+{
+ SKININFO si = {0};
+ SKINREC *pr;
+ WCHAR szText[MAX_PATH*2] = {0};
+ INT typeID, index;
+
+ index = (INT)SendMessageW(hwndCtrl, LB_GETCURSEL, 0, 0L);
+ if (idxSelected == index) return;
+
+ pr = (SKINREC*)SendMessageW(hwndCtrl, LB_GETITEMDATA, index, 0L);
+ if (pr && LB_ERR != (INT)(INT_PTR)pr && pr->bLink) // resolve link
+ {
+ index = ListBox_FindSkinFileIndex(hwndCtrl, ResolveLink(pr), FALSE);
+ pr = (LB_ERR != index) ? (SKINREC*)SendMessageW(hwndCtrl, LB_GETITEMDATA, index, 0L) : NULL;
+ }
+ if (!pr || LB_ERR == (INT)(INT_PTR)pr) { SendMessageW(hwndCtrl, LB_SETCURSEL, idxSelected, 0L); return; }
+ idxSelected = index;
+
+ if (!pr->pszFileName || !*pr->pszFileName) szSelectionPath[0] = 0x00;
+ else StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), pr->pszFileName);
+
+ ZeroMemory(&si, sizeof(SKININFO));
+ si.cbSize = sizeof(SKININFO);
+ si.fMask = SIF_PREVIEW;
+ StringCchCopyW(si.szName, SI_NAMEMAX, pr->pszName);
+
+ GetSkinInfo(BuildFullPath(SKINDIR, szSelectionPath, szText, sizeof(szText)/sizeof(wchar_t)), &si);
+
+ switch(si.type)
+ {
+ case SKIN_TYPE_MODERN: typeID = IDS_MODERN; break;
+ case SKIN_TYPE_CLASSIC: typeID = IDS_CLASSIC; break;
+ default: typeID = IDS_UNKNOWN; break;
+ }
+
+ SetDlgItemTextW(hwnd, IDC_EDT_NAME, si.szName);
+ SetDlgItemTextW(hwnd, IDC_EDT_TYPE, getStringW(typeID, NULL, 0));
+ SetDlgItemTextW(hwnd, IDC_EDT_AUTHOR, si.szAuthor);
+ SetDlgItemTextW(hwnd, IDC_EDT_VERSION, si.szVersion);
+ if (!si.hPreview) si.hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_NO), FALSE);
+ if (si.hPreview)
+ {
+ HBRUSH hb = (HBRUSH)SendMessageW(hwnd, WM_CTLCOLORSTATIC, NULL, (LPARAM)GetDlgItem(hwnd, IDC_PIC_PREVIEW));
+ WABlendOnColor(si.hPreview, RGB(137,145,156));
+ si.hPreview = WAResizeImage(si.hPreview, PREVIEW_WIDTH, PREVIEW_HEIGHT, hb);
+ if (!si.hPreview) si.hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_NO), FALSE);
+ }
+
+ HBITMAP hPrev = (HBITMAP)SendDlgItemMessageW(hwnd, IDC_PIC_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)si.hPreview);
+ if (hPrev) DeleteObject(hPrev);
+}
+
+void setup_page_skin::ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis)
+{
+ SKINREC *pr = (SKINREC*)pdis->itemData;
+ if (pr)
+ {
+ if (pr->pszName) free(pr->pszName);
+ if (pr->pszFileName) free(pr->pszFileName);
+ free(pr);
+ }
+}
+
+void setup_page_skin::ListBox_OnDrawItem(DRAWITEMSTRUCT *pdis)
+{
+ RECT ri;
+ SKINREC *pr = (SKINREC*)pdis->itemData;
+ static UINT trackFocus = 0x0000FFFF;
+
+ if (pdis->itemID == -1) return;
+
+ CopyRect(&ri, &pdis->rcItem);
+ switch(pdis->itemAction)
+ {
+ case ODA_FOCUS:
+ if (0 == (0x0200/*ODS_NOFOCUSRECT*/ & pdis->itemState) && pr)
+ {
+ if (LOWORD(trackFocus) != pdis->itemID || HIWORD(trackFocus) != (ODS_FOCUS & pdis->itemState) ? 0x0001: 0x0000)
+ DrawFocusRect(pdis->hDC, &ri);
+ trackFocus = pdis->itemID | ((ODS_FOCUS & pdis->itemState) ? 0x00010000 : 0x00000000);
+ }
+ else trackFocus = pdis->itemID;
+ return;
+
+ case ODA_SELECT:
+ if (0 == (ODS_SELECTED & pdis->itemState) && pr)
+ ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &ri, L"", 0, NULL);
+ break;
+ }
+
+ if ((ODS_SELECTED & pdis->itemState) && pr)
+ {
+ COLORREF rgb = SetBkColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
+ ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &ri, L"", 0, NULL);
+ SetBkColor(pdis->hDC, rgb);
+ }
+
+ if (pr)
+ {
+ if (pr->pszName)
+ {
+ HFONT hfOld;
+ COLORREF rgb(0);
+
+ if (pr->bLink)
+ {
+ if (!hfLink)
+ {
+ LOGFONTW lf = {0};
+ if (GetObject(GetCurrentObject(pdis->hDC, OBJ_FONT), sizeof(LOGFONTW), &lf))
+ {
+ lf.lfItalic = LINK_FONT_ITALIC;
+ lf.lfWeight = LINK_FONT_WEIGHT;
+ hfLink = CreateFontIndirectW(&lf);
+ }
+ }
+ hfOld = (HFONT)SelectObject(pdis->hDC, hfLink);
+ rgb = SetTextColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
+ }
+ else
+ {
+ hfOld = NULL;
+ rgb = SetTextColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
+ }
+
+ ri.left += 2;
+ COLORREF oldrgb = SetBkColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHT : COLOR_WINDOW));
+ DrawTextW(pdis->hDC, pr->pszName, -1, &ri, DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_WORD_ELLIPSIS);
+ SetBkColor(pdis->hDC, oldrgb);
+ if (pr->bLink && hfOld) SelectObject(pdis->hDC, hfOld);
+ SetTextColor(pdis->hDC, rgb);
+ }
+ }
+ else
+ {
+ HPEN hPen, hPenOld;
+ hPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT));
+ hPenOld = (HPEN)SelectObject(pdis->hDC, hPen);
+ MoveToEx(pdis->hDC, ri.left + 1, ri.top + (ri.bottom - ri.top)/2, NULL);
+ LineTo(pdis->hDC, ri.right - 1, ri.top + (ri.bottom - ri.top)/2);
+ SelectObject(pdis->hDC, hPenOld);
+ }
+}
+
+INT_PTR setup_page_skin::ListBox_OnItemCompare(COMPAREITEMSTRUCT *pcis)
+{ SKINREC *pr1, *pr2;
+ INT cr;
+
+ pr1 = (SKINREC*)pcis->itemData1;
+ pr2 = (SKINREC*)pcis->itemData2;
+ if (pr1 == pr2) return 0;
+ if (!pr1) return (pr2->bLink) ? 1 : -1;
+ if (!pr2) return (pr1->bLink) ? -1 : 1;
+ if (pr1->bLink) return (pr2->bLink) ? (pcis->itemID1 - pcis->itemID2) : -1;
+ if (pr2->bLink) return (pr1->bLink) ? (pcis->itemID1 - pcis->itemID2) : 1;
+ cr = CompareStringW(pcis->dwLocaleId, NORM_IGNORECASE, pr1->pszName, -1, pr2->pszName, -1);
+ if (CSTR_EQUAL == cr)
+ {
+ INT t1, t2;
+ t1 = (SKIN_FILETYPE_WAL == pr1->nType) ? SKIN_FILETYPE_ZIP : ((SKIN_FILETYPE_ZIP == pr1->nType) ? SKIN_FILETYPE_WAL : pr1->nType);
+ t2 = (SKIN_FILETYPE_WAL == pr2->nType) ? SKIN_FILETYPE_ZIP : ((SKIN_FILETYPE_ZIP == pr2->nType) ? SKIN_FILETYPE_WAL : pr2->nType);
+ return t1 - t2;
+ }
+ return cr - 2;
+}
+
+INT_PTR setup_page_skin::ListBox_OnVKeyToItem(HWND hwndLB, WORD vKey, INT index)
+{
+ switch(vKey)
+ {
+ case VK_UP:
+ case VK_LEFT:
+ if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index - 1, 0L)) return index - 2;
+ break;
+ case VK_DOWN:
+ case VK_RIGHT:
+ if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index + 1, 0L)) return index + 2;
+ break;
+ case VK_NEXT:
+ case VK_PRIOR:
+ {
+ RECT rc;
+ INT page, count;
+ GetClientRect(hwndLB, &rc);
+ page = (rc.bottom - rc.top)/(INT)SendMessageW(hwndLB, LB_GETITEMHEIGHT, 0, 0L) - 1;
+ count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L);
+ index = (VK_NEXT == vKey) ? min(index + page, count) : max(0, index - page);
+ if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L)) return index + ((VK_NEXT == vKey) ? 1 : -1);
+ break;
+ }
+ }
+ return -1;
+}
+
+INT_PTR setup_page_skin::ListBox_OnCharToItem(HWND hwndLB, WORD vKey, INT index)
+{
+ return -2;
+}
+
+INT_PTR setup_page_skin::OnInitDialog(HWND hwndFocus, LPARAM lParam)
+{
+ HWND hwndLB, hwndGrp;
+ int count, linksCount(0), index;
+ wchar_t szBuffer[MAX_PATH] = {0};
+
+ idxSelected = -1;
+
+ hwndGrp = GetDlgItem(hwnd, IDC_GRP_PREVIEW);
+ SetWindowLongPtrW(hwndGrp, GWL_STYLE, GetWindowLongPtrW(hwndGrp, GWL_STYLE) | WS_CLIPSIBLINGS);
+
+ hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN);
+ EnumerateSkins(AddSkinToListBox, hwndLB);
+
+ count = sizeof(links)/sizeof(SKINLINK);
+
+ for (int i = count - 1; i >= 0; i--)
+ {
+ SKINREC *pr = (SKINREC*)calloc(1, sizeof(SKINREC));
+ if (pr)
+ {
+ LPCWSTR pszName = links[i].pszName;
+ if (IS_INTRESOURCE(pszName)) pszName = getStringW((INT)(INT_PTR)pszName, szBuffer, sizeof(szBuffer)/sizeof(wchar_t));
+ pr->pszName = _wcsdup(pszName);
+ pr->bLink = TRUE;
+ pr->nType = i;
+
+ if(LB_ERR != ListBox_FindSkinFileIndex(hwndLB, ResolveLink(pr), FALSE) &&
+ LB_ERR != SendMessageW(hwndLB, LB_INSERTSTRING, 0, (LPARAM)pr))
+ {
+ linksCount++;
+ }
+ else
+ {
+ if (pr)
+ {
+ if (pr->pszName) free(pr->pszName);
+ free(pr);
+ }
+ }
+ }
+ }
+
+ if (linksCount) SendMessageW(hwndLB, LB_INSERTSTRING, linksCount, (LPARAM)NULL);
+
+ WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndLB, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ListBoxProc);
+ if (fnOldProc) SetPropW(hwndLB, L"SKINLB", fnOldProc);
+
+ index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE);
+ if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded lang
+ SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L);
+
+ PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_SKIN, LBN_SELCHANGE), (LPARAM)hwndLB);
+ return 0;
+}
+
+void setup_page_skin::OnDestroy(void)
+{
+ if (hfLink) { DeleteObject(hfLink); hfLink = NULL; }
+}
+
+void setup_page_skin::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_SKIN:
+ switch(nEvntID)
+ {
+ case LBN_SELCHANGE: ListBox_OnSelChange(hwndCtrl); break;
+ }
+ break;
+ }
+}
+
+INT_PTR setup_page_skin::OnColorStatic(HDC hdc, HWND hwndCtrl)
+{
+ INT ctrlID = GetDlgCtrlID(hwndCtrl);
+ switch(ctrlID)
+ {
+ case IDC_LBL_NAME:
+ case IDC_LBL_TYPE:
+ case IDC_LBL_AUTHOR:
+ case IDC_LBL_VERSION:
+ SetTextColor(hdc, RGB(0, 70, 213));
+ break;
+ }
+ return NULL;
+}
+
+INT_PTR setup_page_skin::OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_SKIN: ListBox_OnDrawItem(pdis); return TRUE;
+ }
+ return 0;
+}
+
+INT_PTR setup_page_skin::OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_SKIN:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+INT_PTR setup_page_skin::OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_SKIN: ListBox_OnItemDelete(pdis); return TRUE;
+ }
+ return 0;
+}
+
+INT_PTR setup_page_skin::OnCompareItem(INT nCtrlID, COMPAREITEMSTRUCT *pcis)
+{
+ switch(nCtrlID)
+ {
+ case IDC_LB_SKIN: return ListBox_OnItemCompare(pcis);
+ }
+ return 0;
+}
+
+INT_PTR setup_page_skin::OnVKeyToItem(WORD vKey, INT index, HWND hwndCtrl)
+{
+ switch(GetDlgCtrlID(hwndCtrl))
+ {
+ case IDC_LB_SKIN: return ListBox_OnVKeyToItem(hwndCtrl, vKey, index);
+ }
+ return -1;
+}
+
+INT_PTR setup_page_skin::OnCharToItem(WORD vKey, INT index, HWND hwndCtrl)
+{
+ switch(GetDlgCtrlID(hwndCtrl))
+ {
+ case IDC_LB_SKIN: return ListBox_OnCharToItem(hwndCtrl, vKey, index);
+ }
+ return -1;
+}
+
+INT_PTR setup_page_skin::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
+ case WM_DESTROY: OnDestroy(); break;
+ case WM_CTLCOLORSTATIC: return OnColorStatic((HDC)wParam, (HWND)lParam);
+ case WM_DRAWITEM: MSGRESULT(hwnd, OnDrawItem((INT)wParam, (DRAWITEMSTRUCT*)lParam));
+ case WM_MEASUREITEM: MSGRESULT(hwnd, OnMeasureItem((INT)wParam, (MEASUREITEMSTRUCT*)lParam));
+ case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
+ case WM_DELETEITEM: MSGRESULT(hwnd, OnDeleteItem((INT)wParam, (DELETEITEMSTRUCT*)lParam));
+ case WM_COMPAREITEM: return OnCompareItem((INT)wParam, (COMPAREITEMSTRUCT*)lParam);
+ case WM_VKEYTOITEM: return OnVKeyToItem(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
+ case WM_CHARTOITEM: return OnCharToItem(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
+ }
+ return 0;
+}
+
+static BOOL CALLBACK AddSkinToListBox(ENUMSKIN *pes, LPVOID pUser)
+{
+ HWND hwndLB = (HWND)pUser;
+ if (!hwndLB) return FALSE;
+
+ SKINREC *pr = (SKINREC*)calloc(1, sizeof(SKINREC));
+ if (!pr) return FALSE;
+ pr->nType = pes->nType;
+ if (pes->pszName) pr->pszName = _wcsdup(pes->pszName);
+ if (pes->pszFileName) pr->pszFileName = _wcsdup(pes->pszFileName);
+
+ if (LB_ERR == SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)pr))
+ {
+ if (pr->pszName) free(pr->pszName);
+ if (pr->pszFileName) free(pr->pszFileName);
+ free(pr);
+ }
+ return TRUE;
+}
+
+static LPCWSTR ResolveLink(SKINREC *pr)
+{
+ if (!pr) return NULL;
+ if (!pr->bLink) return pr->pszFileName;
+ if (pr->nType < 0 || pr->nType >= sizeof(links)/sizeof(SKINLINK)) return NULL;
+ if(CURRENT_SKIN_ID == (INT)(INT_PTR)links[pr->nType].pszTarget) return config_skin;
+ if (IS_INTRESOURCE(links[pr->nType].pszTarget)) return getStringW((INT)(INT_PTR)links[pr->nType].pszTarget, NULL, 0);
+ return links[pr->nType].pszTarget;
+}
+
+static INT ListBox_FindSkinFileIndex(HWND hwndLB, LPCWSTR pszSkinPath, BOOL bSearchLinks)
+{
+ int index, count;
+ SKINREC *pr;
+ LPCWSTR pszFileName;
+
+ if (!hwndLB) return LB_ERR;
+
+ index = LB_ERR;
+
+ count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L);
+ for (index = 0; index < count; index++)
+ {
+ pr = (SKINREC*) SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L);
+ if (!pr || LB_ERR == (INT)(INT_PTR)pr) continue;
+
+ if (pr->bLink)
+ {
+ if(bSearchLinks) pszFileName = ResolveLink(pr);
+ else continue;
+ }
+ else pszFileName = pr->pszFileName;
+
+ if (!pszSkinPath || !*pszSkinPath)
+ {
+ if (!pszFileName || !*pszFileName) break;
+ }
+ else
+ {
+ if (pszFileName && CSTR_EQUAL == ComparePath(pszSkinPath, pszFileName, SKINDIR)) break;
+ }
+ }
+ return (count == index) ? LB_ERR : index;
+}
+
+static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ setup_page_skin *pInst = (setup_page_skin*)GetPropW(hwnd, L"SETUPPAGE");
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ pInst = (setup_page_skin*)lParam;
+ if (pInst)
+ {
+ pInst->hwnd = hwnd;
+ SetPropW(hwnd, L"SETUPPAGE", pInst);
+ }
+ break;
+ case WM_DESTROY:
+ if (pInst)
+ {
+ pInst->PageDlgProc(uMsg, wParam, lParam);
+ RemovePropW(hwnd, L"SETUPPAGE");
+ pInst = NULL;
+ }
+ break;
+ }
+ return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0;
+}
+
+static LRESULT WINAPI ListBoxProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ WNDPROC fnOldProc = (WNDPROC) GetPropW( hwnd, L"SKINLB" );
+ if ( !fnOldProc ) return DefWindowProcW( hwnd, uMsg, wParam, lParam );
+ switch ( uMsg )
+ {
+ case WM_DESTROY:
+ RemovePropW( hwnd, L"SKINLB" );
+ SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR) fnOldProc );
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ if ( SendMessageW( hwnd, LB_GETITEMDATA, LOWORD( SendMessageW( hwnd, LB_ITEMFROMPOINT, 0, lParam ) ), 0L ) == NULL )
+ return 0;
+ break;
+ }
+
+ return CallWindowProcW( fnOldProc, hwnd, uMsg, wParam, lParam );
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS setup_page_skin
+START_DISPATCH
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(API_SETUPPAGE_GET_NAME, GetName)
+CB(API_SETUPPAGE_CREATEVIEW, CreateView)
+CB(API_SETUPPAGE_SAVE, Save)
+CB(API_SETUPPAGE_REVERT, Revert)
+CB(API_SETUPPAGE_ISDIRTY, IsDirty)
+CB(API_SETUPPAGE_VALIDATE, Validate)
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Winamp/setup/spage_skin.h b/Src/Winamp/setup/spage_skin.h
new file mode 100644
index 00000000..3a380731
--- /dev/null
+++ b/Src/Winamp/setup/spage_skin.h
@@ -0,0 +1,52 @@
+#ifndef WINAMP_SKIN_SETUP_PAGE_HEADER
+#define WINAMP_SKIN_SETUP_PAGE_HEADER
+
+#include "./ifc_setuppage.h"
+
+class setup_page_skin : public ifc_setuppage
+{
+public:
+ setup_page_skin();
+ virtual ~setup_page_skin();
+
+public:
+ size_t AddRef();
+ size_t Release();
+ HRESULT GetName(bool bShort, const wchar_t **pszName);
+ HRESULT Save(HWND hwndText);
+ HRESULT CreateView(HWND hwndParent, HWND *phwnd);
+ HRESULT Revert(void);
+ HRESULT IsDirty(void);
+ HRESULT Validate(void);
+protected:
+ INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam);
+ void OnDestroy(void);
+ INT_PTR OnColorStatic(HDC hdc, HWND hwndCtrl);
+ INT_PTR OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis);
+ INT_PTR OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis);
+ void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl);
+ INT_PTR OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis);
+ INT_PTR OnCompareItem(INT nCtrlID, COMPAREITEMSTRUCT *pcis);
+ INT_PTR OnVKeyToItem(WORD vKey, INT index, HWND hwndCtrl);
+ INT_PTR OnCharToItem(WORD vKey, INT index, HWND hwndCtrl);
+
+ void ListBox_OnDrawItem(DRAWITEMSTRUCT *pdis);
+ void ListBox_OnSelChange(HWND hwndCtrl);
+ void ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis);
+ INT_PTR ListBox_OnItemCompare(COMPAREITEMSTRUCT *pcis);
+ INT_PTR ListBox_OnVKeyToItem(HWND hwndLB, WORD vKey, INT index);
+ INT_PTR ListBox_OnCharToItem(HWND hwndLB, WORD vKey, INT index);
+
+private:
+ size_t ref;
+ HWND hwnd;
+ HFONT hfLink;
+ int idxSelected; // internal crap
+ wchar_t szSelectionPath[MAX_PATH];
+protected:
+ friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ RECVS_DISPATCH;
+};
+
+#endif //WINAMP_SKIN_SETUP_PAGE_HEADER \ No newline at end of file
diff --git a/Src/Winamp/setup/svc_setup.h b/Src/Winamp/setup/svc_setup.h
new file mode 100644
index 00000000..d4cd8106
--- /dev/null
+++ b/Src/Winamp/setup/svc_setup.h
@@ -0,0 +1,123 @@
+#ifndef NULLSOFT_WINAMP_SETUP_SERVICE_HEADER
+#define NULLSOFT_WINAMP_SETUP_SERVICE_HEADER
+
+#include <bfc/dispatch.h>
+#include "./ifc_setuppage.h"
+#include "./ifc_setupjob.h"
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+class api_service;
+typedef BOOL (__cdecl *Plugin_RegisterSetup)(HINSTANCE /*hInstance*/, api_service* /*serviceApi*/);
+
+class __declspec(novtable) svc_setup : public Dispatchable
+{
+protected:
+ svc_setup(void) {};
+ ~svc_setup(void) {};
+public:
+ HRESULT InsertPage(ifc_setuppage *pPage, int* pIndex);
+ HRESULT RemovePage(int index);
+ HRESULT GetPageCount(int* pCount);
+ HRESULT GetPage(int index, ifc_setuppage **pPage);
+ HRESULT GetActiveIndex(int*pIndex);
+ HRESULT Start(HWND hwndWinamp);
+ HRESULT AddJob(ifc_setupjob *pJob);
+ HRESULT RemoveJob(ifc_setupjob *pJob);
+ HRESULT CreateStatusWnd(HWND *phwndStatus);
+ HRESULT Save(HWND hwndStatus);
+ HRESULT ExecJobs(HWND hwndStatus);
+ HRESULT GetWinampWnd(HWND *phwndWinamp); // this call will return S_OK only after setup->Start()
+
+public:
+ DISPATCH_CODES
+ {
+ API_SETUP_INSERT_PAGE = 10,
+ API_SETUP_REMOVE_PAGE = 20,
+ API_SETUP_GET_PAGE_COUNT= 30,
+ API_SETUP_GET_PAGE= 40,
+ API_SETUP_GET_ACTIVE_INDEX = 50,
+ API_SETUP_START = 60,
+ API_SETUP_ADD_JOB = 70,
+ API_SETUP_REMOVE_JOB = 80,
+ API_SETUP_CREATE_STATUSWND = 90,
+ API_SETUP_SAVE = 100,
+ API_SETUP_EXECJOBS = 110,
+ API_SETUP_GETWINAMPWND = 120,
+
+ };
+};
+
+inline HRESULT svc_setup::InsertPage(ifc_setuppage *pPage, int* pIndex)
+{
+ return _call(API_SETUP_INSERT_PAGE, E_NOTIMPL, pPage, pIndex);
+}
+
+inline HRESULT svc_setup::RemovePage(int index)
+{
+ return _call(API_SETUP_REMOVE_PAGE, E_NOTIMPL, index);
+}
+
+inline HRESULT svc_setup::GetPageCount(int* pCount)
+{
+ return _call(API_SETUP_GET_PAGE_COUNT, E_NOTIMPL, pCount);
+}
+
+inline HRESULT svc_setup::GetPage(int index, ifc_setuppage **pPage)
+{
+ return _call(API_SETUP_GET_PAGE, E_NOTIMPL, index, pPage);
+}
+inline HRESULT svc_setup::GetActiveIndex(int*pIndex)
+{
+ return _call(API_SETUP_GET_ACTIVE_INDEX, E_NOTIMPL, pIndex);
+}
+inline HRESULT svc_setup::Start(HWND hwndWinamp)
+{
+ return _call(API_SETUP_START, E_NOTIMPL, hwndWinamp);
+}
+
+inline HRESULT svc_setup::AddJob(ifc_setupjob *pJob)
+{
+ return _call(API_SETUP_ADD_JOB, E_NOTIMPL, pJob);
+}
+
+inline HRESULT svc_setup::RemoveJob(ifc_setupjob *pJob)
+{
+ return _call(API_SETUP_REMOVE_JOB, E_NOTIMPL, pJob);
+}
+
+inline HRESULT svc_setup::CreateStatusWnd(HWND *phwndStatus)
+{
+ return _call(API_SETUP_CREATE_STATUSWND, E_NOTIMPL, phwndStatus);
+}
+
+inline HRESULT svc_setup::Save(HWND hwndStatus)
+{
+ return _call(API_SETUP_SAVE, E_NOTIMPL, hwndStatus);
+}
+
+inline HRESULT svc_setup::ExecJobs(HWND hwndStatus)
+{
+ return _call(API_SETUP_EXECJOBS, E_NOTIMPL, hwndStatus);
+}
+
+inline HRESULT svc_setup::GetWinampWnd(HWND *phwndWinamp)
+{
+ return _call(API_SETUP_GETWINAMPWND, E_NOTIMPL, phwndWinamp);
+}
+
+
+
+// {A7281DEB-9DA8-4ee9-93A8-2E0B8F5F1805}
+static const GUID UID_SVC_SETUP = { 0xa7281deb, 0x9da8, 0x4ee9, { 0x93, 0xa8, 0x2e, 0xb, 0x8f, 0x5f, 0x18, 0x5 } };
+
+
+#endif //NULLSOFT_WINAMP_SETUP_SERVICE_HEADER
diff --git a/Src/Winamp/setup/wa_classic_preview.png b/Src/Winamp/setup/wa_classic_preview.png
new file mode 100644
index 00000000..7a02a1da
--- /dev/null
+++ b/Src/Winamp/setup/wa_classic_preview.png
Binary files differ