Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

View file

@ -0,0 +1,91 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <vector>
class ifc_omservice;
class __declspec(novtable) SetupGroupFilter
{
public:
typedef enum
{
serviceIgnore = 0x00000000,
serviceInclude = 0x00000001,
serviceForceSubscribe = 0x00000002,
serviceForceUnsubscribe = 0x00000004,
} FilterResult;
protected:
SetupGroupFilter(const GUID *filterId);
virtual ~SetupGroupFilter();
public:
static HRESULT CreateInstance(const GUID *filterId, SetupGroupFilter **instance);
public:
virtual ULONG AddRef();
virtual ULONG Release();
virtual HRESULT GetId(GUID *filterId);
virtual HRESULT Initialize() = 0;
virtual HRESULT ProcessService(ifc_omservice *service, UINT *filterResult) = 0;
protected:
typedef std::vector<UINT> ServiceIdList;
static BOOL CALLBACK AppendServiceIdCallback(UINT serviceId, void *data);
protected:
ULONG ref;
GUID id;
};
// {2F45FBDF-4372-4def-B20C-C6F1BAE5AE85}
static const GUID FUID_SetupFeaturedGroupFilter =
{ 0x2f45fbdf, 0x4372, 0x4def, { 0xb2, 0xc, 0xc6, 0xf1, 0xba, 0xe5, 0xae, 0x85 } };
class SetupFeaturedGroupFilter : public SetupGroupFilter
{
protected:
SetupFeaturedGroupFilter();
~SetupFeaturedGroupFilter();
public:
static HRESULT CreateInstance(SetupFeaturedGroupFilter **instance);
public:
HRESULT Initialize();
HRESULT ProcessService(ifc_omservice *service, UINT *filterResult);
protected:
ServiceIdList filterList;
};
// {7CA8722D-8B11-43a0-8F55-533C9DE3D73E}
static const GUID FUID_SetupKnownGroupFilter =
{ 0x7ca8722d, 0x8b11, 0x43a0, { 0x8f, 0x55, 0x53, 0x3c, 0x9d, 0xe3, 0xd7, 0x3e } };
class SetupKnownGroupFilter : public SetupGroupFilter
{
protected:
SetupKnownGroupFilter();
~SetupKnownGroupFilter();
public:
static HRESULT CreateInstance(SetupKnownGroupFilter **instance);
public:
HRESULT Initialize();
HRESULT ProcessService(ifc_omservice *service, UINT *filterResult);
protected:
ServiceIdList filterList;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER

View file

@ -0,0 +1,71 @@
#define GUID_DEFINE
#include "../../winamp/setup/svc_setup.h"
#undef GUID_DEFINE
#include "./setupPage.h"
#include "../api__ml_online.h"
static HRESULT Setup_RegisterPage()
{
HRESULT hr;
svc_setup *setupSvc;
SetupPage *page;
if (FAILED(WasabiApi_LoadDefaults()) ||
NULL == OMBROWSERMNGR ||
NULL == OMSERVICEMNGR ||
NULL == OMUTILITY)
{
return E_UNEXPECTED;
}
setupSvc = QueryWasabiInterface(svc_setup, UID_SVC_SETUP);
if (NULL == setupSvc)
return E_POINTER;
page = SetupPage::CreateInstance();
if (NULL == page)
hr = E_OUTOFMEMORY;
else
{
// try to insert before 'feedback' (if present)
// otherwise dump at the end of the pages list.
int index = 0xFFFFF;
if (FAILED(setupSvc->GetPageCount(&index)))
index = 0xFFFFF;
else if (index > 0 && index == 3)
index--;
hr = setupSvc->InsertPage(page, &index);
if (SUCCEEDED(hr))
setupSvc->AddJob((ifc_setupjob*)page);
page->Release();
}
ReleaseWasabiInterface(UID_SVC_SETUP, setupSvc);
return hr;
}
EXTERN_C _declspec(dllexport) BOOL RegisterSetup(HINSTANCE hInstance, api_service *waServices)
{
// check the current date and if past November 30th 2013
// then we will prevent the online page from being shown
time_t now = time(0);
struct tm *tn = localtime(&now);
tn->tm_sec = tn->tm_min = tn->tm_hour = 0;
if (mktime(tn) >= 1387497600)
return FALSE;
if (FAILED(WasabiApi_Initialize(hInstance, waServices)))
return FALSE;
BOOL result = SUCCEEDED(Setup_RegisterPage());
WasabiApi_Release();
return result;
}

View file

@ -0,0 +1,80 @@
#include "./common.h"
#include "./setupDetails.h"
#include "./setupServicePanel.h"
EXTERN_C ATOM DETAILS_PROP = 0;
HMODULE hEditModule = NULL;
BOOL SetupDetails_Initialize()
{
if (0 == DETAILS_PROP)
{
DETAILS_PROP = GlobalAddAtom(L"omSetupDetailsProp");
if (0 == DETAILS_PROP) return FALSE;
}
if (NULL == (hEditModule = LoadLibrary(L"riched20.dll")))
return FALSE;
return TRUE;
}
void SetupDetails_Uninitialize()
{
if (NULL != hEditModule)
{
FreeLibrary(hEditModule);
hEditModule = NULL;
}
if (0 != DETAILS_PROP)
{
GlobalDeleteAtom(DETAILS_PROP);
DETAILS_PROP = 0;
}
}
void SetupDetails_SetDescription(HWND hEdit, LPCWSTR pszText)
{
SetWindowText(hEdit, pszText);
DWORD originalStyle = GetWindowStyle(hEdit);
DWORD windowStyle = originalStyle & ~WS_VSCROLL;
INT lineCount = (INT)SendMessage(hEdit, EM_GETLINECOUNT, 0, 0L);
if (lineCount > 0)
{
INT charIndex = (INT)SendMessage(hEdit, EM_LINEINDEX, (WPARAM)(lineCount - 1), 0L);
if (-1 != charIndex)
{
LRESULT result = SendMessage(hEdit, EM_POSFROMCHAR, charIndex, 0L);
POINTS pts = MAKEPOINTS(result);
RECT clientRect;
if (GetClientRect(hEdit, &clientRect) && pts.y > (clientRect.bottom - 14))
{
windowStyle |= WS_VSCROLL;
}
}
}
if (windowStyle != originalStyle)
{
SetWindowLongPtr(hEdit, GWL_STYLE, windowStyle);
SetWindowPos(hEdit, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
}
ShowWindow(hEdit, SW_HIDE);
if (0 != ShowWindow(hEdit, (L'\0' != *pszText) ? SW_SHOWNA : SW_HIDE))
InvalidateRect(hEdit, NULL, TRUE);
}
HWND SetupDetails_CreateServiceView(HWND hParent, LPCWSTR pszName, ifc_omservice *service)
{
return ServicePanel::CreateInstance(hParent, pszName, service, NULL);
}
BOOL SetupDetails_GetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax)
{
return (BOOL)SendMessage(hwnd, NSDM_GETUNIQUENAME, (WPARAM)cchBufferMax, (LPARAM)pszBuffer);
}

View file

@ -0,0 +1,30 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class ifc_omservice;
class SetupGroup;
class SetupListboxItem;
#define NSDM_FIRST (WM_APP + 7)
#define NSDM_GETUNIQUENAME (NSDM_FIRST + 0)
EXTERN_C ATOM DETAILS_PROP;
BOOL SetupDetails_Initialize();
void SetupDetails_Uninitialize();
HWND SetupDetails_CreateServiceView(HWND hParent, LPCWSTR pszName, ifc_omservice *service);
HWND SetupDetails_CreateGroupView(HWND hParent, LPCWSTR pszName, SetupGroup *group);
BOOL SetupDetails_GetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax);
// internal
void SetupDetails_SetDescription(HWND hEdit, LPCWSTR pszText);
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER

View file

@ -0,0 +1,284 @@
#include "./setupDetails.h"
#include "../common.h"
#include "../resource.h"
#include "../api__ml_online.h"
#include "../../winamp/commandLink.h"
#include "./setupGroup.h"
#include <commctrl.h>
#include <strsafe.h>
#ifndef IDC_HELPLINK
#define IDC_HELPLINK 10000
#endif
struct GROUPDETAILSCREATEPARAM
{
GROUPDETAILSCREATEPARAM() : group(NULL), name(NULL) {}
SetupGroup *group;
LPCWSTR name;
};
struct GROUPDETAILS
{
GROUPDETAILS() : group(NULL), name(NULL), fontTitle(NULL) {}
SetupGroup *group;
LPWSTR name;
HFONT fontTitle;
};
#define GetDetails(__hwnd) ((GROUPDETAILS*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
static INT_PTR WINAPI GroupDetails_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND SetupDetails_CreateGroupView(HWND hParent, LPCWSTR pszName, SetupGroup *group)
{
GROUPDETAILSCREATEPARAM param;
param.group = group;
param.name = pszName;
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_GROUPDETAILS, hParent, GroupDetails_DialogProc, (LPARAM)&param);
}
static void GroupDetails_SetTitle(HWND hwnd, SetupGroup *group)
{
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
if (NULL == hTitle) return;
WCHAR szBuffer[128] = {0};
if (NULL == group ||
FAILED(group->GetLongName(szBuffer, ARRAYSIZE(szBuffer))))
{
szBuffer[0] = L'\0';
}
GROUPDETAILS *details = GetDetails(hwnd);
if (NULL != details && NULL == details->fontTitle)
{
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
lf.lfWidth = 0;
lf.lfWeight = FW_DONTCARE;
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
details->fontTitle = CreateFontIndirect(&lf);
}
if (NULL != details->fontTitle)
{
SendMessage(hTitle, WM_SETFONT, (WPARAM)details->fontTitle, 0L);
}
}
SetWindowText(hTitle, szBuffer);
InvalidateRect(hTitle, NULL, TRUE);
}
static void GroupDetails_SetDescription(HWND hwnd, SetupGroup *group)
{
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
if (NULL == hDescription) return;
WCHAR szBuffer[4096] = {0};
if (NULL == group ||
FAILED(group->GetDescription(szBuffer, ARRAYSIZE(szBuffer))))
{
szBuffer[0] = L'\0';
}
SetupDetails_SetDescription(hDescription, szBuffer);
}
static BOOL GroupDetails_ShowHelp(HWND hwnd)
{
INT result = (INT)(INT_PTR)ShellExecuteW(hwnd, L"open",
L"https://help.winamp.com/hc/articles/8112753225364-Online-Services-Security",
NULL, NULL, SW_SHOWNORMAL);
return (result > 32);
}
static void GroupDetails_UpdateLayout(HWND hwnd, BOOL fRedraw)
{
RECT clientRect, rect;
if(FALSE == GetClientRect(hwnd, &clientRect))
return;
UINT commonFlags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE != fRedraw) commonFlags |= SWP_NOREDRAW;
LONG bottomLine = clientRect.bottom;
HWND hControl;
SIZE linkSize;
RECT linkMargins;
if (NULL != (hControl = GetDlgItem(hwnd, IDC_HELPLINK)) &&
CommandLink_GetIdealSize(hControl, &linkSize))
{
if (!CommandLink_GetMargins(hControl, &linkMargins))
SetRectEmpty(&linkMargins);
if (linkSize.cy > 0)
bottomLine -= linkSize.cy;
SetWindowPos(hControl, NULL, clientRect.left + 4, bottomLine, linkSize.cx, linkSize.cy, commonFlags);
}
else
{
ZeroMemory(&linkSize, sizeof(linkSize));
SetRectEmpty(&linkMargins);
}
if (NULL != (hControl = GetDlgItem(hwnd, IDC_HELPTEXT)))
{
LONG x = clientRect.left + 4 + linkSize.cx/* - linkMargins.right*/;
LONG y = 0;
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
HFONT originalFont = (HFONT)SelectObject(hdc, font);
TEXTMETRICW tm;
if (GetTextMetricsW(hdc, &tm))
y = tm.tmHeight;
SelectObject(hdc, originalFont);
ReleaseDC(hControl, hdc);
}
SetWindowPos(hControl, NULL, x, clientRect.bottom - linkMargins.bottom - y, clientRect.right - x, y, commonFlags);
}
if (NULL != (hControl = GetDlgItem(hwnd, IDC_DESCRIPTION)) &&
FALSE != GetWindowRect(hControl, &rect))
{
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
SetWindowPos(hControl, NULL, rect.left, rect.right, rect.right - rect.left, bottomLine - rect.top,
commonFlags | SWP_NOMOVE);
}
}
static INT_PTR GroupDetails_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
{
GROUPDETAILSCREATEPARAM *param = (GROUPDETAILSCREATEPARAM*)lParam;
GROUPDETAILS *details = (GROUPDETAILS*)calloc(1, sizeof(GROUPDETAILS));
if (NULL == details) return FALSE;
if (!SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), details))
return FALSE;
if (NULL != param)
{
if (NULL != param->group)
{
details->group = param->group;
details->group->AddRef();
}
details->name = Plugin_CopyString(param->name);
}
HINSTANCE winampInstance = (NULL != WASABI_API_APP) ? WASABI_API_APP->main_gethInstance() : NULL;
if (NULL != winampInstance)
{
WCHAR szBuffer[256] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_CLICKHERE, szBuffer, ARRAYSIZE(szBuffer));
HWND hLink = CreateWindowExW(WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT, NWC_COMMANDLINKW, szBuffer,
WS_VISIBLE | WS_CHILD | WS_TABSTOP | CLS_ALWAYSUNDERLINE | CLS_DEFAULTCOLORS /* | CLS_HOTTRACK */,
0, 0, 0, 0, hwnd, (HMENU)IDC_HELPLINK, winampInstance, NULL);
if (NULL != hLink)
{
SendMessageW(hLink, WM_SETFONT, (WPARAM)SendMessageW(hwnd, WM_GETFONT, 0, 0L), 0L);
}
}
GroupDetails_UpdateLayout(hwnd, FALSE);
if (NULL != param)
{
GroupDetails_SetTitle(hwnd, param->group);
GroupDetails_SetDescription(hwnd, param->group);
}
return FALSE;
}
static void GroupDetails_OnDestroy(HWND hwnd)
{
GROUPDETAILS *details = GetDetails(hwnd);
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
if (NULL != details)
{
if (NULL != details->group)
details->group->Release();
if (NULL != details->fontTitle)
DeleteObject(details->fontTitle);
Plugin_FreeString(details->name);
}
}
static INT_PTR GroupDetails_OnDialogColor(HWND hwnd, HDC hdc, HWND hControl)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
return 0;
}
static INT_PTR GroupDetails_OnStaticColor(HWND hwnd, HDC hdc, HWND hControl)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
return 0;
}
static LRESULT GroupDetails_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh)
{
switch(controlId)
{
case IDC_HELPLINK:
if (NM_CLICK == pnmh->code)
GroupDetails_ShowHelp(hwnd);
return TRUE;
}
return 0;
}
static BOOL GroupDetails_OnGetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer)
return FALSE;
GROUPDETAILS *details = GetDetails(hwnd);
return SUCCEEDED(StringCchCopy(pszBuffer, cchBufferMax,
(NULL != details && NULL != details->name) ? details->name : L""));
}
static INT_PTR WINAPI GroupDetails_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return GroupDetails_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: GroupDetails_OnDestroy(hwnd); break;
case WM_CTLCOLORDLG: return GroupDetails_OnDialogColor(hwnd, (HDC)wParam, (HWND)lParam);
case WM_CTLCOLORSTATIC: return GroupDetails_OnStaticColor(hwnd, (HDC)wParam, (HWND)lParam);
case WM_NOTIFY: MSGRESULT(hwnd, GroupDetails_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam));
case NSDM_GETUNIQUENAME: MSGRESULT(hwnd, GroupDetails_OnGetUniqueName(hwnd, (LPWSTR)lParam, (UINT)wParam));
}
return 0;
}

View file

@ -0,0 +1,596 @@
#include "./setupDetails.h"
#include "../common.h"
#include "../resource.h"
#include "../wasabi.h"
#include <ifc_omservice.h>
#include <ifc_omservicedetails.h>
#include <ifc_omcachemanager.h>
#include <ifc_omserviceevent.h>
#include <ifc_omcachegroup.h>
#include <ifc_omcacherecord.h>
#include <ifc_imageloader.h>
#include <ifc_omgraphics.h>
#include <ifc_omserviceeventmngr.h>
#include <shlwapi.h>
#include <strsafe.h>
#define GetPanel(__hwnd) ((ServicePanel*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
#define GET_IDETAILS(__service, __details)\
(NULL != (service) && SUCCEEDED((service)->QueryInterface(IFC_OmServiceDetails, (void**)&(__details))))
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND OmSetupDetails_CreateServiceView(HWND hParent, ifc_omservice *service)
{
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_SERVICEDETAILS, hParent, ServicePanel_DialogProc, (LPARAM)service);
}
static HFONT ServicePanel_PickTitleFont(HWND hwnd, LPCWSTR pszTitle, INT cchTitle, INT maxWidth)
{
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
if (0 == GetObject(dialogFont, sizeof(LOGFONT), &lf))
return NULL;
HFONT titleFont = NULL;
if (cchTitle > 0)
{
LOGFONT lf;
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
lf.lfWidth = 0;
lf.lfWeight = FW_DONTCARE;
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT origFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
SIZE textSize;
INT heightLimit = (lf.lfHeight < 0) ? 1 : -1;
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
do
{
textSize.cx = 0;
if (NULL != titleFont) DeleteObject(titleFont);
titleFont = CreateFontIndirect(&lf);
if (NULL != titleFont)
{
SelectObject(hdc, titleFont);
GetTextExtentPoint32(hdc, pszTitle, cchTitle, &textSize);
}
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
} while(textSize.cx > maxWidth && lf.lfHeight != heightLimit);
if (0 == textSize.cx)
{
DeleteObject(titleFont);
titleFont = NULL;
}
SelectObject(hdc, origFont);
ReleaseDC(hwnd, hdc);
}
}
}
if (NULL == titleFont &&
0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
titleFont = CreateFontIndirect(&lf);
}
return titleFont;
}
static void ServicePanel_SetServiceName(HWND hwnd, ifc_omservice *service)
{
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
if (NULL == hTitle) return;
WCHAR szBuffer[128];
if (NULL == service ||
FAILED(service->GetName(szBuffer, ARRAYSIZE(szBuffer))))
{
szBuffer[0] = L'\0';
}
SERVICEDETAILS *details = GetDetails(hwnd);
if (NULL != details)
{
INT cchBuffer = lstrlen(szBuffer);
RECT rc;
GetClientRect(hTitle, &rc);
HFONT titleFont = ServicePanel_PickTitleFont(hwnd, szBuffer, cchBuffer, rc.right - rc.left);
if (NULL != titleFont)
{
if (NULL != details->fontTitle) DeleteObject(details->fontTitle);
details->fontTitle = titleFont;
SendMessage(hTitle, WM_SETFONT, (WPARAM)details->fontTitle, 0L);
}
}
SetWindowText(hTitle, szBuffer);
InvalidateRect(hTitle, NULL, TRUE);
}
static void ServicePanel_SetServiceDescription(HWND hwnd, ifc_omservice *service)
{
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
if (NULL == hDescription) return;
WCHAR szBuffer[4096] = {0};
ifc_omservicedetails *details = 0;
if (GET_IDETAILS(service, details))
{
details->GetDescription(szBuffer, ARRAYSIZE(szBuffer));
details->Release();
}
OmSetupDetails_SetDescription(hDescription, szBuffer);
}
static LPCWSTR ServicePanel_FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax)
{
SYSTEMTIME st;
ZeroMemory(&st, sizeof(SYSTEMTIME));
LPCWSTR cursor;
cursor = pszDate;
INT index = 0;
for(;;)
{
INT iVal;
if (FALSE == StrToIntEx(cursor, STIF_DEFAULT, &iVal) || iVal < 1)
{
index = 0;
break;
}
if (0 == index)
{
if (iVal < 2000 || iVal > 2100)
break;
st.wYear = iVal;
index++;
}
else if (1 == index)
{
if (iVal < 1 || iVal > 12)
break;
st.wMonth = iVal;
index++;
}
else if (2 == index)
{
if (iVal < 1 || iVal > 31)
break;
st.wDay = iVal;
index++;
}
else
{
index = 0;
break;
}
while(L'\0' != *cursor && L'-' != *cursor) cursor++;
if (L'-' == *cursor) cursor++;
if (L'\0' == *cursor)
break;
}
if (3 == index &&
0 != GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszBuffer, cchBufferMax))
{
return pszBuffer;
}
return pszDate;
}
static HRESULT ServicePanel_GetFullName(ifc_omservicedetails *details, LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
*pszBuffer = L'\0';
HRESULT hr = S_OK;
if (NULL != details)
{
hr = details->GetAuthorFirst(pszBuffer, cchBufferMax);
if (SUCCEEDED(hr))
{
UINT cchBuffer = lstrlen(pszBuffer);
LPWSTR cursor = pszBuffer + cchBuffer;
size_t remaining = cchBufferMax - cchBuffer;
if (cursor != pszBuffer)
{
hr = StringCchCopyEx(cursor, remaining, L" ", &cursor, &remaining, 0);
if (SUCCEEDED(hr))
{
hr = details->GetAuthorLast(cursor, (UINT)remaining);
if (FAILED(hr) || L'\0' == *cursor)
{
pszBuffer[cchBuffer] = L'\0';
}
}
}
}
}
return hr;
}
static void ServicePanel_SetServiceMeta(HWND hwnd, ifc_omservice *service)
{
HWND hMeta = GetDlgItem(hwnd, IDC_SERVICEMETA);
if (NULL == hMeta) return;
WCHAR szBuffer[512] = {0};
ifc_omservicedetails *svcdetails = 0;
if (GET_IDETAILS(service, svcdetails))
{
HRESULT hr = S_OK;
LPWSTR cursor = szBuffer;
WCHAR szValue[256] = {0}, szPrefix[64] = {0};
size_t remaining = ARRAYSIZE(szBuffer);
if (SUCCEEDED(ServicePanel_GetFullName(svcdetails, szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
{
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_BYAUTHOR, szPrefix, ARRAYSIZE(szPrefix));
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
L"%s%s", szPrefix, szValue);
}
if (SUCCEEDED(svcdetails->GetUpdated(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
{
if (cursor != szBuffer)
hr = StringCchCopyEx(cursor, remaining, L"\r\n", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
if (SUCCEEDED(hr))
{
WCHAR szDate[128] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_LASTUPDATED, szPrefix, ARRAYSIZE(szPrefix));
StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
L"%s%s", szPrefix, ServicePanel_FormatDate(szValue, szDate, ARRAYSIZE(szDate)));
}
}
svcdetails->Release();
}
SERVICEDETAILS *details = GetDetails(hwnd);
if (NULL != details && NULL == details->fontMeta)
{
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma");
lf.lfWidth = 0;
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
lf.lfQuality = ANTIALIASED_QUALITY;
details->fontMeta = CreateFontIndirect(&lf);
}
if (NULL != details->fontMeta)
{
SendMessage(hMeta, WM_SETFONT, (WPARAM)details->fontMeta, 0L);
}
}
SetWindowText(hMeta, szBuffer);
if (0 != ShowWindow(hMeta, (L'\0' != szBuffer[0]) ? SW_SHOWNA : SW_HIDE))
InvalidateRect(hMeta, NULL, TRUE);
}
static void ServicePanel_SetThumbnail(HWND hwnd, ifc_omservice *service)
{
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
if (NULL == hThumbnail) return;
SendMessage(hThumbnail, WM_SETREDRAW, FALSE, 0L);
HBITMAP hBitmap;
BITMAPINFOHEADER header;
void *pixelData;
WCHAR szPath[2048];
ifc_omservicedetails *details = 0;
if (GET_IDETAILS(service, details))
{
if (SUCCEEDED(details->GetThumbnail(szPath, ARRAYSIZE(szPath))))
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(OMUTILITY->GetCacheManager(&cacheManager)))
{
ifc_omcachegroup *cacheGroup;
if (SUCCEEDED(cacheManager->Find(L"thumbnail", TRUE, &cacheGroup, NULL)))
{
ifc_omcacherecord *cacheRecord;
if (SUCCEEDED(cacheGroup->Find(szPath, TRUE, &cacheRecord, FALSE)))
{
cacheRecord->Release();
}
cacheGroup->Release();
}
cacheManager->Release();
}
}
details->Release();
}
ifc_omimageloader *imageLoader;
if (SUCCEEDED(OMUTILITY->QueryImageLoader(NULL, szPath, FALSE, &imageLoader)))
{
if (FAILED(imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData)))
hBitmap = NULL;
imageLoader->Release();
}
if (NULL == hBitmap &&
SUCCEEDED(OMUTILITY->QueryImageLoader(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_SERVICE64X64_IMAGE), FALSE, &imageLoader)))
{
if (FAILED(imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData)))
hBitmap = NULL;
imageLoader->Release();
}
HBITMAP hTest = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
if (NULL != hTest)
DeleteObject(hTest);
if (NULL != hBitmap)
{
hTest = (HBITMAP)SendMessage(hThumbnail, STM_GETIMAGE, IMAGE_BITMAP, 0L);
if (hTest != hBitmap)
{ // this is XP and up image copy was created and alpha channel will be handled properly
DeleteObject(hBitmap);
}
else
{ // fix alpha channel
if (32 == header.biBitCount)
{
HDC hdcFixed = CreateCompatibleDC(NULL);
if (NULL != hdcFixed)
{
BITMAPINFOHEADER headerFixed;
CopyMemory(&headerFixed, &header, sizeof(BITMAPINFOHEADER));
BYTE *pixelsFixed;
INT cx = header.biWidth;
INT cy = abs(header.biHeight);
HBITMAP bitmapFixed = CreateDIBSection(NULL, (LPBITMAPINFO)&headerFixed, DIB_RGB_COLORS, (void**)&pixelsFixed, NULL, 0);
if (NULL != bitmapFixed)
{
HBITMAP bitmapOrig = (HBITMAP)SelectObject(hdcFixed, bitmapFixed);
HBRUSH hb = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdcFixed, (LPARAM)hwnd);
if (NULL == hb)
hb = GetSysColorBrush(COLOR_3DFACE);
RECT rect;
SetRect(&rect, 0, 0, cx, cy);
FillRect(hdcFixed, &rect, hb);
ifc_omgraphics *graphics;
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
{
HDC hdcSrc = CreateCompatibleDC(NULL);
if (NULL != hdcSrc)
{
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xFF;
bf.AlphaFormat = AC_SRC_ALPHA;
RECT blendRect;
SetRect(&blendRect, 0, 0, cx, cy);
graphics->Premultiply((BYTE*)pixelData, cx, cy);
graphics->AlphaBlend(hdcFixed, &blendRect, hdcSrc, &blendRect, bf);
SelectObject(hdcSrc, bitmapSrcOrig);
DeleteDC(hdcSrc);
}
graphics->Release();
}
SelectObject(hdcFixed, bitmapOrig);
SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmapFixed);
DeleteObject(hBitmap);
}
DeleteDC(hdcFixed);
}
}
}
}
RECT clientRect;
if (GetClientRect(hThumbnail, &clientRect))
{
INT cx = clientRect.right - clientRect.left;
INT cy = clientRect.bottom - clientRect.top;
if (64 != cx || 64 != cy)
{
SetWindowPos(hThumbnail, NULL, 0, 0, 64, 64, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
}
SendMessage(hThumbnail, WM_SETREDRAW, TRUE, 0L);
if (0 != ShowWindow(hThumbnail, (NULL != hBitmap) ? SW_SHOWNA : SW_HIDE))
InvalidateRect(hThumbnail, NULL, TRUE);
}
static void CALLBACK ServicePanel_OnServiceNotify(UINT serviceUid, UINT callbackType, UINT callbackParam, ULONG_PTR user)
{
HWND hwnd = (HWND)user;
if (NULL == hwnd) return;
SERVICEDETAILS *details = GetDetails(hwnd);
if (NULL == details ||
NULL == details->service ||
serviceUid != details->service->GetId())
{
return;
}
switch(callbackType)
{
case OmService::eventServiceModified:
if (0 != (OmService::modifiedName & callbackParam))
ServicePanel_SetServiceName(hwnd, details->service);
if (0 != (OmService::modifiedDescription & callbackParam))
ServicePanel_SetServiceDescription(hwnd, details->service);
if (0 != ((OmService::modifiedAuthor | OmService::modifiedDate) & callbackParam))
ServicePanel_SetServiceMeta(hwnd, details->service);
if (0 != (OmService::modifiedThumbnail & callbackParam))
ServicePanel_SetThumbnail(hwnd, details->service);
break;
}
}
static INT_PTR ServicePanel_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
{
ifc_omservice *service = (ifc_omservice*)lParam;
SERVICEDETAILS *details = (SERVICEDETAILS*)malloc(sizeof(SERVICEDETAILS));
if (NULL == details) return FALSE;
ZeroMemory(details, sizeof(SERVICEDETAILS));
if (!SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), details))
return FALSE;
details->service = service;
details->service->AddRef();
ServicePanel_SetServiceName(hwnd, service);
ServicePanel_SetServiceDescription(hwnd, service);
ServicePanel_SetThumbnail(hwnd, service);
ServicePanel_SetServiceMeta(hwnd, service);
if (NULL != service)
{
ifc_omserviceeventmngr *eventManager;
if (SUCCEEDED(service->GetEventManager(&eventManager)))
{
if (SUCCEEDED(eventManager->RegisterHandler(eventHander)))
{
details->eventHandler = eventHandler;
}
else
{
eventHandler->Release();
}
}
}
return FALSE;
}
static void ServicePanel_OnDestroy(HWND hwnd)
{
OMSERVICEMNGR->UnregisterCallback(ServicePanel_OnServiceNotify, (ULONG_PTR)hwnd);
SERVICEDETAILS *details = GetDetails(hwnd);
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
if (NULL != details)
{
if (NULL != details->service)
details->service->Release();
if (NULL != details->fontTitle)
DeleteObject(details->fontTitle);
if (NULL != details->fontMeta)
DeleteObject(details->fontMeta);
}
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
if (NULL != hThumbnail)
{
HBITMAP hBitmap = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, 0L);
if (NULL != hBitmap)
DeleteObject(hBitmap);
}
}
static INT_PTR ServicePanel_OnDialogColor(HWND hwnd, HDC hdc, HWND hControl)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
return 0;
}
static INT_PTR ServicePanel_OnStaticColor(HWND hwnd, HDC hdc, HWND hControl)
{
INT_PTR result = 0;
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
result = (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
INT controlId = GetDlgCtrlID(hControl);
switch(controlId)
{
case IDC_SERVICEMETA:
{
COLORREF rgbBk = GetBkColor(hdc);
COLORREF rgbFg = GetTextColor(hdc);
ifc_omgraphics *graphics;
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
{
graphics->BlendColor(rgbFg, rgbBk, 180, &rgbFg);
graphics->Release();
}
SetTextColor(hdc, rgbFg);
}
break;
}
return result;
}
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return ServicePanel_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: ServicePanel_OnDestroy(hwnd); break;
case WM_CTLCOLORDLG: return ServicePanel_OnDialogColor(hwnd, (HDC)wParam, (HWND)lParam);
case WM_CTLCOLORSTATIC: return ServicePanel_OnStaticColor(hwnd, (HDC)wParam, (HWND)lParam);
}
return 0;
}

View file

@ -0,0 +1,929 @@
#include "./setupGroup.h"
#include "./setupGroupFilter.h"
#include "./setupListboxLabel.h"
#include "./setupDetails.h"
#include "./setupPage.h"
#include "../common.h"
#include "../api__ml_online.h"
#include "../resource.h"
#include "../serviceHost.h"
#include "../serviceHelper.h"
#include "../../nu/menuHelpers.h"
#include <vector>
#include <ifc_omservice.h>
#include <ifc_omstorage.h>
#include <ifc_omstorageasync.h>
#include <ifc_omserviceenum.h>
#include <ifc_omfilestorage.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <algorithm>
typedef std::vector<ifc_omservice*> ServiceList;
#define GROUP_MARGINCX 0
#define GROUP_MARGINCY 1
#define TEXT_OFFSET_LEFT 2
#define TEXT_OFFSET_BOTTOM 2
#define TEXT_ALIGN (TA_LEFT | TA_BOTTOM)
SetupGroup::SetupGroup(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle)
: ref(1), id(groupId), name(NULL), flags(0), emptyLabel(NULL), errorCode(S_OK), hPage(NULL),
longName(NULL), description(NULL), address(NULL), loadResult(NULL), style(fStyle), loadComplete(NULL)
{
name = Plugin_DuplicateResString(pszName);
address = Plugin_DuplicateResString(pszAddress);
this->storageId = (NULL != storageId) ? *storageId : GUID_NULL;
this->filterId = (NULL != filterId) ? *filterId : GUID_NULL;
InitializeCriticalSection(&lock);
}
SetupGroup::~SetupGroup()
{
Plugin_FreeResString(name);
Plugin_FreeResString(address);
SetLongName(NULL);
SetDescription(NULL);
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
list[index]->Release();
}
if (NULL != emptyLabel)
emptyLabel->Release();
if (NULL != loadResult)
{
ifc_omstorage *storage;
HRESULT hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
if (SUCCEEDED(hr))
{
storage->RequestAbort(loadResult, TRUE);
}
loadResult->Release();
loadResult = NULL;
}
if (NULL != loadComplete)
CloseHandle(loadComplete);
LeaveCriticalSection(&lock);
DeleteCriticalSection(&lock);
}
SetupGroup *SetupGroup::CreateInstance(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle)
{
return new SetupGroup(groupId, pszName, pszAddress, storageId, filterId, fStyle);
}
ULONG SetupGroup::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupGroup::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT SetupGroup::GetName(LPWSTR pszBuffer, INT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
HRESULT hr;
if (NULL != name)
{
if (IS_INTRESOURCE(name))
{
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)name, pszBuffer, cchBufferMax);
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
}
else
{
hr = StringCchCopyW(pszBuffer, cchBufferMax, name);
}
}
else
{
hr = StringCchCopyW(pszBuffer, cchBufferMax, L"Unknown");
}
return hr;
}
HRESULT SetupGroup::GetLongName(LPWSTR pszBuffer, INT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
HRESULT hr;
if (NULL == longName)
return GetName(pszBuffer, cchBufferMax);
if (IS_INTRESOURCE(longName))
{
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)longName, pszBuffer, cchBufferMax);
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
}
else
{
hr = StringCchCopyW(pszBuffer, cchBufferMax, longName);
}
return hr;
}
HRESULT SetupGroup::GetDescription(LPWSTR pszBuffer, INT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
HRESULT hr;
if (NULL != description && IS_INTRESOURCE(description))
{
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)description, pszBuffer, cchBufferMax);
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
}
else
{
hr = StringCchCopyEx(pszBuffer, cchBufferMax, description, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
return hr;
}
size_t SetupGroup::GetRecordCount()
{
return list.size();
}
size_t SetupGroup::GetListboxCount()
{
if (0 != (flagCollapsed & flags)) return 0;
size_t listSize = list.size();
if (0 == listSize)
{
return (NULL != emptyLabel && FALSE == emptyLabel->IsNameNull()) ? 1 : 0;
}
return listSize;
}
SetupListboxItem *SetupGroup::GetListboxItem(size_t index)
{
if (0 != (flagCollapsed & flags)) return NULL;
size_t listSize = list.size();
if (0 == listSize)
{
return (NULL != emptyLabel && FALSE == emptyLabel->IsNameNull()) ? emptyLabel : NULL;
}
return list[index];
}
BOOL SetupGroup::IsModified()
{
size_t index = list.size();
while(index--)
{
if (list[index]->IsModified())
return TRUE;
}
return FALSE;
}
BOOL SetupGroup::IsExpanded()
{
return (0 == (flagCollapsed & flags));
}
void SetupGroup::SetExpanded(BOOL fExpanded)
{
if ((FALSE == fExpanded) == (FALSE == IsExpanded()))
return;
if (FALSE == fExpanded)
flags |= flagCollapsed;
else
flags &= ~flagCollapsed;
}
void SetupGroup::Clear(BOOL fInvalidate)
{
size_t index = list.size();
if (0 == index) return;
EnterCriticalSection(&lock);
while(index--)
{
SetupRecord *record = list[index];
if (NULL != record)
{
record->Release();
}
}
list.clear();
LeaveCriticalSection(&lock);
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_EMPTYGROUP), FALSE);
if (FALSE != fInvalidate && NULL != hPage)
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)id, NULL);
}
static void CALLBACK SetupGroup_LoadCallback(ifc_omstorageasync *result)
{
if (NULL == result) return;
SetupGroup *group;
if (SUCCEEDED(result->GetData((void**)&group)) && NULL != group)
{
group->OnLoadCompleted();
}
}
__inline static int __cdecl SetupGroup_AlphabeticalSorter(const void *elem1, const void *elem2)
{
SetupRecord *record1 = (SetupRecord*)elem1;
SetupRecord *record2 = (SetupRecord*)elem2;
if (NULL == record1 || NULL == record2)
return (INT)(INT_PTR)(record1 - record2);
ifc_omservice *svc1 = record1->GetService();
ifc_omservice *svc2 = record2->GetService();
if (NULL == svc1 || NULL == svc2)
return (INT)(INT_PTR)(svc1 - svc2);
WCHAR szBuffer1[256] = {0}, szBuffer2[256] = {0};
if (FAILED(svc1->GetName(szBuffer1, ARRAYSIZE(szBuffer1))))
szBuffer1[0] = L'\0';
if (FAILED(svc2->GetName(szBuffer2, ARRAYSIZE(szBuffer2))))
szBuffer2[0] = L'\0';
return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, szBuffer1, -1, szBuffer2, -1) - 2;
}
__inline static bool __cdecl SetupGroup_AlphabeticalSorter_V2(const void* elem1, const void* elem2)
{
return SetupGroup_AlphabeticalSorter(elem1, elem2) < 0;
}
void SetupGroup::OnLoadCompleted()
{
ifc_omstorage *storage;
HRESULT hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
if (SUCCEEDED(hr))
{
ifc_omserviceenum *serviceEnum;
hr = storage->EndLoad(loadResult, &serviceEnum);
if (SUCCEEDED(hr))
{
SetupGroupFilter *filter;
if (FAILED(SetupGroupFilter::CreateInstance(&filterId, &filter)))
{
filter = NULL;
}
else if (FAILED(filter->Initialize()))
{
filter->Release();
filter = NULL;
}
EnterCriticalSection(&lock);
ifc_omservice *service;
UINT filterResult, defaultFilter;
defaultFilter = SetupGroupFilter::serviceInclude;
if (0 != (styleDefaultUnsubscribed & style))
defaultFilter |= SetupGroupFilter::serviceForceUnsubscribe;
else if (0 != (styleDefaultSubscribed & style))
defaultFilter |= SetupGroupFilter::serviceForceSubscribe;
while(S_OK == serviceEnum->Next(1, &service, NULL))
{
filterResult = defaultFilter;
if (NULL != filter && FAILED(filter->ProcessService(service, &filterResult)))
filterResult = defaultFilter;
if (0 == (SetupGroupFilter::serviceInclude & filterResult))
{
service->Release();
service = NULL;
continue;
}
if (0 != (SetupGroupFilter::serviceForceUnsubscribe & filterResult))
ServiceHelper_Subscribe(service, TRUE, 0);
else if (0 != (SetupGroupFilter::serviceForceSubscribe & filterResult))
ServiceHelper_Subscribe(service, FALSE, 0);
if (0 != (styleSaveAll & style))
ServiceHelper_MarkModified(service, (UINT)-1, (UINT)-1);
SetupRecord *record = SetupRecord::CreateInstance(service);
if (NULL != record)
{
if (0 != (SetupGroupFilter::serviceForceUnsubscribe & filterResult))
record->SetSelected(FALSE);
else if (0 != (SetupGroupFilter::serviceForceSubscribe & filterResult))
record->SetSelected(TRUE);
list.push_back(record);
}
service->Release();
}
if (0 != (styleSortAlphabetically & style))
{
//qsort(list.first(), list.size(), sizeof(SetupRecord*), SetupGroup_AlphabeticalSorter);
std::sort(list.begin(), list.end(), SetupGroup_AlphabeticalSorter_V2);
}
LeaveCriticalSection(&lock);
serviceEnum->Release();
if (NULL != filter)
filter->Release();
}
storage->Release();
}
EnterCriticalSection(&lock);
loadResult->Release();
loadResult = NULL;
if (NULL != loadComplete)
{
SetEvent(loadComplete);
CloseHandle(loadComplete);
loadComplete = NULL;
}
LeaveCriticalSection(&lock);
LPCWSTR pszText = MAKEINTRESOURCE(((FAILED(hr)) ? IDS_SETUP_GROUPLOADFAILED : IDS_SETUP_EMPTYGROUP));
SetEmptyText( pszText, TRUE);
}
HRESULT SetupGroup::RequestReload()
{
if (NULL == OMSERVICEMNGR)
return E_UNEXPECTED;
HRESULT hr;
EnterCriticalSection(&lock);
if (NULL != loadResult)
hr = E_PENDING;
else
{
if (NULL != loadComplete)
{
CloseHandle(loadComplete);
loadComplete = NULL;
}
Clear(FALSE);
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_LOADINGGROUP), TRUE);
ifc_omstorage *storage;
hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
if (SUCCEEDED(hr))
{
ServiceHost *serviceHost;
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
serviceHost = NULL;
hr = storage->BeginLoad(address, serviceHost, SetupGroup_LoadCallback, this, &loadResult);
storage->Release();
if (NULL != serviceHost)
serviceHost->Release();
}
if (FAILED(hr))
{
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_GROUPLOADFAILED), TRUE);
}
}
LeaveCriticalSection(&lock);
return hr;
}
void SetupGroup::SetPageWnd(HWND hPage)
{
this->hPage = hPage;
}
HRESULT SetupGroup::SignalLoadCompleted(HANDLE event)
{
HRESULT hr;
if (NULL == event) return E_INVALIDARG;
EnterCriticalSection(&lock);
if (NULL == loadResult)
{
SetEvent(event);
hr = S_OK;
}
else
{
if (NULL != loadComplete)
CloseHandle(loadComplete);
if (FALSE == DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &loadComplete, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
hr = S_OK;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT SetupGroup::Save(SetupLog *log)
{
HRESULT hr(S_OK);
size_t index = list.size();
while(index--)
{
if (FAILED(list[index]->Save(log)))
hr = E_FAIL;
}
return hr;
}
void SetupGroup::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
{
COLORREF rgbBk, rgbText;
if (0 != (ODS_DISABLED & state))
{
rgbBk = GetBkColor(hdc);
rgbText = GetSysColor(COLOR_GRAYTEXT);
}
else
{
if (0 != (ODS_SELECTED & state))
{
if (0 == (ODS_INACTIVE & state))
{
rgbBk = GetSysColor(COLOR_HIGHLIGHT);
rgbText = GetSysColor(COLOR_HIGHLIGHTTEXT);
}
else
{
rgbBk = GetSysColor(COLOR_3DFACE);
rgbText = GetSysColor(COLOR_WINDOWTEXT);
}
}
else
{
rgbBk = GetSysColor(COLOR_WINDOW);
rgbText = GetSysColor(COLOR_WINDOWTEXT);
}
}
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
}
HBRUSH SetupGroup::GetBrush(HDC hdc, UINT state)
{
if (0 != (ODS_DISABLED & state))
{
return GetSysColorBrush(COLOR_WINDOW);
}
if (0 != (ODS_COMBOBOXEDIT & state))
{
return GetSysColorBrush(COLOR_WINDOWTEXT);
}
if (0 != (ODS_SELECTED & state))
{
return GetSysColorBrush( (0 == (ODS_INACTIVE & state)) ? COLOR_HIGHLIGHT : COLOR_3DFACE);
}
return GetSysColorBrush(COLOR_WINDOW);
}
BOOL SetupGroup::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
{
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return FALSE;
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
SIZE imageSize;
if (!instance->GetExpandboxMetrics(hdc, IsExpanded(), &imageSize))
ZeroMemory(&imageSize, sizeof(SIZE));
if (NULL != cy)
{
*cy = 0;
TEXTMETRIC tm;
if (GetTextMetrics(hdc, &tm))
{
*cy = tm.tmHeight + tm.tmExternalLeading;
if (imageSize.cy > (INT)*cy) *cy = imageSize.cy;
*cy += GROUP_MARGINCY*2;
}
}
if (NULL != cx)
{
*cx = imageSize.cx;
WCHAR szBuffer[128] = {0};
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
{
INT cchBuffer = lstrlenW(szBuffer);
SIZE textSize;
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
{
*cx += textSize.cx;
}
}
if (0 != *cx) *cx += GROUP_MARGINCX*2;
}
SelectObject(hdc, originalFont);
ReleaseDC(instance->GetHwnd(), hdc);
return TRUE;
}
static void SetupGroup_DrawFrame(HDC hdc, const RECT *prc, INT width, COLORREF rgbFrame)
{
if (width > 0)
{
COLORREF rgbOld = SetBkColor(hdc, rgbFrame);
RECT rcPart;
SetRect(&rcPart, prc->left, prc->top, prc->right, prc->top + width);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
SetRect(&rcPart, prc->left, prc->bottom - width, prc->right, prc->bottom);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
SetRect(&rcPart, prc->left, prc->top + width, prc->left + width, prc->bottom - width);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
SetRect(&rcPart, prc->right - width, prc->top + width, prc->right, prc->bottom - width);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
if (rgbOld != rgbFrame)
SetBkColor(hdc, rgbOld);
}
}
BOOL SetupGroup::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
{
LONG paintLeft = prc->left + GROUP_MARGINCX;
RECT partRect;
SetRectEmpty(&partRect);
COLORREF rgbBk, rgbText;
GetColors(hdc, state, &rgbBk, &rgbText);
COLORREF origBk = SetBkColor(hdc, rgbBk);
COLORREF origText = SetTextColor(hdc, rgbText);
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
HRGN backRgn, rgn;
backRgn = CreateRectRgnIndirect(prc);
rgn = CreateRectRgn(0,0,0,0);
SetRectEmpty(&partRect);
if (instance->GetExpandboxMetrics(hdc, IsExpanded(), (((SIZE*)&partRect) + 1)))
{
INT space = (prc->bottom - prc->top) - (partRect.bottom- partRect.top);
INT offsetY = space / 2 + space%2;
if (offsetY < 0) offsetY = 0;
OffsetRect(&partRect, paintLeft, prc->top + offsetY);
if (instance->DrawExpandbox(hdc, IsExpanded(), &partRect, rgbBk, rgbText))
{
paintLeft = partRect.right;
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
}
WCHAR szBuffer[128] = {0};
INT cchBuffer = 0;
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
cchBuffer = lstrlenW(szBuffer);
SetRect(&partRect, paintLeft, prc->top, prc->right, prc->bottom);
if (ExtTextOut(hdc, partRect.left + TEXT_OFFSET_LEFT, partRect.bottom - TEXT_OFFSET_BOTTOM,
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
{
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
COLORREF rgbLine = ColorAdjustLuma(rgbBk, -150, TRUE);
if (rgbLine != rgbBk)
{
RECT lineRect;
SetRect(&lineRect, prc->left, prc->bottom - 1, prc->right, prc->bottom);
SetBkColor(hdc, rgbLine);
if (ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL))
{
if (SetRectRgn(rgn, lineRect.left, lineRect.top, lineRect.right, lineRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
SetBkColor(hdc, rgbBk);
}
if (0 != (flagMenuActive & flags))
{
COLORREF rgbFrame = rgbLine; //ColorAdjustLuma(GetSysColor(COLOR_HIGHLIGHT), 100, TRUE);
SetupGroup_DrawFrame(hdc, prc, 1, rgbFrame);
if (SetRectRgn(rgn, prc->left + 1, prc->top + 1, prc->right - 1, prc->bottom - 1))
CombineRgn(backRgn, backRgn, rgn, RGN_AND);
}
if (NULL != backRgn)
{
FillRgn(hdc, backRgn, GetBrush(hdc, state));
DeleteObject(backRgn);
}
if (NULL != rgn)
DeleteObject(rgn);
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
DrawFocusRect(hdc, prc);
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
if (origBk != rgbBk) SetBkColor(hdc, origBk);
if (origText != rgbText) SetTextColor(hdc, origText);
return TRUE;
}
INT_PTR SetupGroup::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
{
switch(vKey)
{
case VK_SPACE:
InvertExpanded(instance);
return -2;
}
return -1;
}
BOOL SetupGroup::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupGroup::MouseLeave(SetupListbox *instance, const RECT *prcItem)
{
return FALSE;
}
BOOL SetupGroup::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupGroup::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupGroup::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
InvertExpanded(instance);
return TRUE;
}
BOOL SetupGroup::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return TRUE;
}
BOOL SetupGroup::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
HMENU hMenu = instance->GetContextMenu(SetupListbox::menuGroupContext);
if (NULL == hMenu)
return FALSE;
hMenu = MenuHelper_DuplcateMenu(hMenu);
if (NULL == hMenu) return FALSE;
MENUITEMINFO mi;
mi.cbSize = sizeof(MENUITEMINFO);
mi.fMask = MIIM_STATE;
GetMenuItemInfo(hMenu, ID_GROUP_TOGGLE, FALSE, &mi);
mi.fMask = 0;
if (0 == (MFS_DEFAULT & mi.fState))
{
mi.fMask |= MIIM_STATE;
mi.fState |= MFS_DEFAULT;
}
WCHAR szBuffer[128] = {0};
WASABI_API_LNGSTRINGW_BUF(((IsExpanded()) ? IDS_COLLAPSE : IDS_EXPAND), szBuffer, ARRAYSIZE(szBuffer));
mi.fMask |= MIIM_STRING;
mi.dwTypeData = szBuffer;
if (0 != mi.fMask)
SetMenuItemInfo(hMenu, ID_GROUP_TOGGLE, FALSE, &mi);
if (0 == list.size())
{
EnableMenuItem(hMenu, ID_GROUP_SELECTALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hMenu, ID_GROUP_UNSELECTALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (0 != (flagLoading & flags))
{
EnableMenuItem(hMenu, ID_GROUP_RELOAD, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
MapWindowPoints(instance->GetHwnd(), HWND_DESKTOP, &pt, 1);
flags |= flagMenuActive;
instance->InvalidateRect(prcItem, TRUE);
INT cmd = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, instance->GetHwnd(), NULL);
if (0 != cmd)
{
Command(instance, cmd, 0);
}
DestroyMenu(hMenu);
flags &= ~flagMenuActive;
instance->InvalidateRect(prcItem, TRUE);
return TRUE;
}
void SetupGroup::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
{
}
void SetupGroup::InvertExpanded(SetupListbox *instance)
{
if (FALSE != IsExpanded())
ValidateSelection(instance);
SetExpanded(!IsExpanded());
if (NULL != instance)
{
instance->UpdateCount();
UpdateWindow(instance->GetHwnd());
}
}
void SetupGroup::SelectAll(SetupListbox *instance, BOOL fSelect)
{
size_t index = list.size();
INT baseIndex;
if (NULL == instance || FALSE == instance->GetIndex(this, &baseIndex))
baseIndex = -1;
else
baseIndex++;
while(index--)
{
SetupRecord *record = list[index];
if (NULL != record && !record->IsDisabled())
{
if ((FALSE == fSelect) != (FALSE == record->IsSelected()))
{
record->SetSelected(fSelect);
if (0 == (flagCollapsed & flags) && NULL != instance && -1 != baseIndex)
{
instance->InvalidateItem((INT)(baseIndex + index), TRUE);
}
}
}
}
}
void SetupGroup::SetEmptyText(LPCWSTR pszText, BOOL fInvalidate)
{
if (NULL == emptyLabel)
emptyLabel = SetupListboxLabel::CreateInstance(pszText);
else
emptyLabel->SetName(pszText);
if (FALSE != fInvalidate && NULL != hPage)
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)id, NULL);
}
HWND SetupGroup::CreateDetailsView(HWND hParent)
{
WCHAR szName[64] = {0};
if (FALSE == GetUniqueName(szName, ARRAYSIZE(szName)))
szName[0] = L'\0';
return SetupDetails_CreateGroupView(hParent, szName, this);
}
BOOL SetupGroup::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer ||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"grp_id_%d", id)))
{
return FALSE;
}
return TRUE;
}
void SetupGroup::SetLongName(LPCWSTR pszText)
{
if (NULL != longName && !IS_INTRESOURCE(longName))
Plugin_FreeString(longName);
longName = NULL;
if (NULL != pszText)
longName = (IS_INTRESOURCE(pszText)) ? (LPWSTR)pszText : Plugin_CopyString(pszText);
}
void SetupGroup::SetDescription(LPCWSTR pszText)
{
if (NULL != description && !IS_INTRESOURCE(description))
Plugin_FreeString(description);
description = NULL;
if (NULL != pszText)
description = (IS_INTRESOURCE(pszText)) ? (LPWSTR)pszText : Plugin_CopyString(pszText);
}
void SetupGroup::ValidateSelection(SetupListbox *instance)
{
if (NULL == instance)
return;
SetupListboxItem *selection = instance->GetSelection();
if (NULL != selection)
{
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (list[index] == selection)
{
instance->SetSelection(this);
break;
}
}
LeaveCriticalSection(&lock);
}
}
void SetupGroup::Command(SetupListbox *instance, INT commandId, INT eventId)
{
switch(commandId)
{
case ID_GROUP_TOGGLE:
InvertExpanded(instance);
break;
case ID_GROUP_SELECTALL:
SelectAll(instance, TRUE);
break;
case ID_GROUP_UNSELECTALL:
SelectAll(instance, FALSE);
break;
case ID_GROUP_RELOAD:
ValidateSelection(instance);
RequestReload();
break;
}
}

View file

@ -0,0 +1,131 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./setupRecord.h"
#include "./setupListbox.h"
#include <vector>
class SetupListboxLabel;
class SetupLog;
class SetupPage;
class ifc_omstorage;
class SetupGroup : public SetupListboxItem
{
public:
typedef enum
{
styleDefaultUnsubscribed = 0x00000001,
styleDefaultSubscribed = 0x00000002,
styleSortAlphabetically = 0x00000008,
styleSaveAll = 0x00000010,
} GroupStyles;
protected:
typedef enum
{
flagCollapsed = 0x0001,
flagMenuActive = 0x0002,
flagLoading = 0x0004,
} GroupFlags;
protected:
SetupGroup(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle);
~SetupGroup();
public:
static SetupGroup *CreateInstance(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle);
public:
ULONG AddRef();
ULONG Release();
INT GetId() { return id; }
HRESULT GetName(LPWSTR pszBuffer, INT cchBufferMax);
HRESULT GetLongName(LPWSTR pszBuffer, INT cchBufferMax);
HRESULT GetDescription(LPWSTR pszBuffer, INT cchBufferMax);
size_t GetRecordCount();
SetupRecord *GetRecord(size_t index) { return list[index]; }
size_t GetListboxCount();
SetupListboxItem *GetListboxItem(size_t index);
BOOL IsModified();
BOOL IsExpanded();
void SetExpanded(BOOL fExpanded);
void SelectAll(SetupListbox *instance, BOOL fSelect);
HRESULT RequestReload();
HRESULT Save(SetupLog *log);
void SetEmptyText(LPCWSTR pszText, BOOL fInvalidate);
void SetLongName(LPCWSTR pszText);
void SetDescription(LPCWSTR pszText);
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
HBRUSH GetBrush(HDC hdc, UINT state);
HRESULT SignalLoadCompleted(HANDLE event);
void ValidateSelection(SetupListbox *instance);
/* SetupListboxItem */
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
BOOL IsDisabled() { return FALSE; }
void Command(SetupListbox *instance, INT commandId, INT eventId);
HWND CreateDetailsView(HWND hParent);
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
void SetError(HRESULT code) { errorCode = code; }
HRESULT GetError() { return errorCode; }
void Clear(BOOL fInvalidate);
void SetPageWnd(HWND hPage);
protected:
void InvertExpanded(SetupListbox *instance);
void OnLoadCompleted();
private:
friend static void CALLBACK SetupGroup_LoadCallback(ifc_omstorageasync *result);
protected:
ULONG ref;
INT id;
LPWSTR name;
LPWSTR longName;
LPWSTR description;
UINT style;
UINT flags;
LPWSTR address;
GUID storageId;
GUID filterId;
HRESULT errorCode;
std::vector<SetupRecord*> list;
SetupListboxLabel *emptyLabel;
CRITICAL_SECTION lock;
ifc_omstorageasync *loadResult;
HWND hPage;
HANDLE loadComplete;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER

View file

@ -0,0 +1,226 @@
#include "./setupGroupFilter.h"
#include "../api__ml_online.h"
#include "../serviceHost.h"
#include "../config.h"
#include <ifc_omservice.h>
#include <ifc_omstorage.h>
#include <ifc_omserviceenum.h>
#include <ifc_omfilestorage.h>
SetupGroupFilter::SetupGroupFilter(const GUID *filterId)
: ref(1)
{
id = (NULL != filterId) ? *filterId : GUID_NULL;
}
SetupGroupFilter::~SetupGroupFilter()
{
}
HRESULT SetupGroupFilter::CreateInstance(const GUID *filterId, SetupGroupFilter **instance)
{
if (NULL == filterId)
{
*instance = NULL;
return E_INVALIDARG;
}
if (FALSE != IsEqualGUID(*filterId, FUID_SetupFeaturedGroupFilter))
return SetupFeaturedGroupFilter::CreateInstance((SetupFeaturedGroupFilter**)instance);
if (FALSE != IsEqualGUID(*filterId, FUID_SetupKnownGroupFilter))
return SetupKnownGroupFilter::CreateInstance((SetupKnownGroupFilter**)instance);
*instance = NULL;
return E_NOINTERFACE;
}
ULONG SetupGroupFilter::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupGroupFilter::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT SetupGroupFilter::GetId(GUID *filterId)
{
if (NULL == filterId)
return E_POINTER;
*filterId = id;
return S_OK;
}
BOOL CALLBACK SetupGroupFilter::AppendServiceIdCallback(UINT serviceId, void *data)
{
ServiceIdList *list = (ServiceIdList*)data;
if (NULL == list) return FALSE;
list->push_back(serviceId);
return TRUE;
}
SetupFeaturedGroupFilter::SetupFeaturedGroupFilter()
: SetupGroupFilter(&FUID_SetupFeaturedGroupFilter)
{
}
SetupFeaturedGroupFilter::~SetupFeaturedGroupFilter()
{
}
HRESULT SetupFeaturedGroupFilter::CreateInstance(SetupFeaturedGroupFilter **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new SetupFeaturedGroupFilter();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT SetupFeaturedGroupFilter::Initialize()
{
HRESULT hr;
ifc_omstorage *storage;
filterList.clear();
if (NULL == OMSERVICEMNGR)
return E_UNEXPECTED;
hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageIni, &storage);
if(FAILED(hr))
return hr;
ServiceHost *serviceHost;
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
serviceHost = NULL;
ifc_omserviceenum *serviceEnum;
hr = storage->Load(L"*.ini", serviceHost, &serviceEnum);
if(SUCCEEDED(hr))
{
ifc_omservice *service;
while(S_OK == serviceEnum->Next(1, &service, NULL) && NULL != service)
{
filterList.push_back(service->GetId());
}
serviceEnum->Release();
}
storage->Release();
ServiceIdList promoList;
Config_ReadServiceIdList("Setup", "featuredExtra", ',', AppendServiceIdCallback, &promoList);
ServiceIdList historyList;
Config_ReadServiceIdList("Setup", "featuredHistory", ',', AppendServiceIdCallback, &historyList);
size_t index = historyList.size();
size_t filterIndex, filterSize = filterList.size();
while(index--)
{
size_t promoSize = promoList.size();
for(filterIndex = 0; filterIndex < promoSize; filterIndex++)
{
if (promoList[filterIndex] == historyList[index])
{
promoList.erase(promoList.begin() + filterIndex);
break;
}
}
if (filterIndex == promoSize)
{
for(filterIndex = 0; filterIndex < filterSize; filterIndex++)
{
if (filterList[filterIndex] == historyList[index])
break;
}
if (filterIndex == filterSize)
filterList.push_back(historyList[index]);
}
}
return hr;
}
HRESULT SetupFeaturedGroupFilter::ProcessService(ifc_omservice *service, UINT *filterResult)
{
if (NULL == service)
return E_INVALIDARG;
if (NULL == filterResult)
return E_POINTER;
size_t index = filterList.size();
while(index--)
{
if (filterList[index] == service->GetId())
{
filterList.erase(filterList.begin() + index);
*filterResult = serviceIgnore;
break;
}
}
return S_OK;
}
SetupKnownGroupFilter::SetupKnownGroupFilter()
: SetupGroupFilter(&FUID_SetupKnownGroupFilter)
{
}
SetupKnownGroupFilter::~SetupKnownGroupFilter()
{
}
HRESULT SetupKnownGroupFilter::CreateInstance(SetupKnownGroupFilter **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new SetupKnownGroupFilter();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT SetupKnownGroupFilter::Initialize()
{
Config_ReadServiceIdList("Setup", "featuredExtra", ',', AppendServiceIdCallback, &filterList);
return S_OK;
}
HRESULT SetupKnownGroupFilter::ProcessService(ifc_omservice *service, UINT *filterResult)
{
if (NULL == service)
return E_INVALIDARG;
if (NULL == filterResult)
return E_POINTER;
size_t index = filterList.size();
while(index--)
{
if (filterList[index] == service->GetId())
{
filterList.erase(filterList.begin() + index);
*filterResult &= ~serviceForceUnsubscribe;
*filterResult |= serviceForceSubscribe;
break;
}
}
return S_OK;
}

View file

@ -0,0 +1,190 @@
#include "./setupGroupList.h"
#include "../api__ml_online.h"
#include <strsafe.h>
SetupGroupList::SetupGroupList()
: ref(1)
{
}
SetupGroupList::~SetupGroupList()
{
size_t index = list.size();
while(index--)
{
list[index]->Release();
}
}
SetupGroupList *SetupGroupList::CreateInstance()
{
return new SetupGroupList();
}
ULONG SetupGroupList::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupGroupList::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
BOOL SetupGroupList::AddGroup(SetupGroup *group)
{
if (NULL == group) return FALSE;
list.push_back(group);
group->AddRef();
return TRUE;
}
size_t SetupGroupList::GetGroupCount()
{
return list.size();
}
BOOL SetupGroupList::IsModified()
{
size_t index = list.size();
while(index--)
{
if (list[index]->IsModified())
return TRUE;
}
return FALSE;
}
BOOL SetupGroupList::FindGroupIndex(SetupGroup *group, size_t *groupIndex)
{
if (NULL == group) return FALSE;
size_t index = list.size();
while(index--)
{
if (list[index] == group)
{
if (NULL != groupIndex)
*groupIndex = index;
return TRUE;
}
}
return FALSE;
}
HRESULT SetupGroupList::FindGroupById(UINT groupId, SetupGroup **group)
{
if (NULL == group) return E_POINTER;
size_t index = list.size();
while(index--)
{
if (list[index]->GetId() == groupId)
{
*group = list[index];
(*group)->AddRef();
return S_OK;
}
}
return S_FALSE;
}
size_t SetupGroupList::GetListboxCount()
{
size_t recordCount = list.size();
size_t index = recordCount;
while(index--)
{
recordCount += list[index]->GetListboxCount();
}
return recordCount;
}
HRESULT SetupGroupList::Save(SetupLog *log)
{
HRESULT hr(S_OK);
size_t index = list.size();
while(index--)
{
if (FAILED(list[index]->Save(log)))
hr = E_FAIL;
}
return hr;
}
HRESULT SetupGroupList::FindListboxItem(size_t listboxId, SetupListboxItem **listboxItem)
{
if (NULL == listboxItem) return E_POINTER;
size_t index = 0;
size_t groupCount = list.size();
SetupGroup *group;
for (size_t i = 0; i < groupCount; i++)
{
group = list[i];
if (index == listboxId)
{
*listboxItem = (SetupListboxItem*)group;
return S_OK;
}
index++;
size_t itemCount;
if (0 != (itemCount = group->GetListboxCount()))
{
if (listboxId < (index + itemCount))
{
size_t itemIndex = (listboxId - index);
*listboxItem = group->GetListboxItem(itemIndex);
return S_OK;
}
index += itemCount;
}
}
return E_NOTIMPL;
}
INT SetupGroupList::GetListboxItem(SetupListboxItem *item)
{
if (NULL == item) return LB_ERR;
size_t index = 0;
size_t groupCount = list.size();
SetupGroup *group;
SetupListboxItem *groupItem;
for (size_t i = 0; i < groupCount; i++)
{
group = list[i];
if (item == group)
return (INT)index;
index++;
size_t itemCount = group->GetListboxCount();
for (size_t j = 0; j < itemCount; j++)
{
groupItem = group->GetListboxItem(j);
if (groupItem == item)
return (INT)index;
index++;
}
}
return LB_ERR;
}
void SetupGroupList::SetPageWnd(HWND hPage)
{
size_t index = list.size();
while(index--)
{
list[index]->SetPageWnd(hPage);
}
}

View file

@ -0,0 +1,52 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./setupGroup.h"
#include <vector>
class SetupListboxItem;
class SetupLog;
class SetupGroupList
{
protected:
SetupGroupList();
~SetupGroupList();
public:
static SetupGroupList *CreateInstance();
public:
ULONG AddRef();
ULONG Release();
BOOL AddGroup(SetupGroup *group);
SetupGroup *GetGroup(size_t index) { return list[index]; }
size_t GetGroupCount();
BOOL FindGroupIndex(SetupGroup *group, size_t *groupIndex);
HRESULT FindGroupById(UINT groupId, SetupGroup **group);
BOOL IsModified();
HRESULT Save(SetupLog *log);
size_t GetListboxCount();
INT GetListboxItem(SetupListboxItem *item);
HRESULT FindListboxItem(size_t listboxId, SetupListboxItem **listboxItem);
void SetPageWnd(HWND hPage);
protected:
ULONG ref;
std::vector<SetupGroup*> list;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER

View file

@ -0,0 +1,282 @@
#include "./setupImage.h"
#include "../api__ml_online.h"
#include <shlwapi.h>
static BOOL SetupImage_CopyImage(HDC hdc, HBITMAP bitmapDst, INT x, INT y, INT cx, INT cy, HBITMAP bitmapSrc, INT srcX, INT srcY)
{
BOOL resultOk = FALSE;
HDC hdcDst = CreateCompatibleDC(hdc);
HDC hdcSrc = CreateCompatibleDC(hdc);
if (NULL != hdcDst && NULL != hdcSrc)
{
HBITMAP bitmapDstOrig = (HBITMAP)SelectObject(hdcDst, bitmapDst);
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, bitmapSrc);
resultOk = BitBlt(hdcDst, x, y, cx, cy, hdcSrc, srcX, srcY, SRCCOPY);
SelectObject(hdcDst, bitmapDstOrig);
SelectObject(hdcSrc, bitmapSrcOrig);
}
if (NULL != hdcDst) DeleteDC(hdcDst);
if (NULL != hdcSrc) DeleteDC(hdcSrc);
return resultOk;
}
static BOOL SetupImage_ColorizeImage(BYTE *pPixels, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, LONG dstX, LONG dstY, COLORREF rgbBk, COLORREF rgbFg, BOOL removeAlpha)
{
LONG pitch;
INT step;
BYTE rFg, gFg, bFg;
LPBYTE srcCursor, srcLine;
LPBYTE dstLine;
if (bpp < 24) return FALSE;
step = (bpp>>3);
pitch = cx*step;
while (pitch%4) pitch++;
rFg = GetRValue(rgbFg); gFg = GetGValue(rgbFg); bFg = GetBValue(rgbFg);
INT bK = (bFg - GetBValue(rgbBk));
INT gK = (gFg - GetGValue(rgbBk));
INT rK = (rFg - GetRValue(rgbBk));
srcLine = pPixels + pitch * y + x*step;
dstLine = pPixels + pitch * dstY + dstX*step;
if (24 == bpp)
{
for (; cy-- != 0; srcLine += pitch, dstLine += pitch )
{
LONG i;
LPBYTE dstCursor;
for (i = cx, srcCursor = srcLine, dstCursor = dstLine ; i-- != 0; srcCursor += 3, dstCursor +=3)
{
dstCursor[0] = bFg - (bK*(255 - srcCursor[0])>>8);
dstCursor[1] = gFg - (gK*(255 - srcCursor[1])>>8);
dstCursor[2] = rFg - (rK*(255 - srcCursor[2])>>8);
}
}
}
else
{
// nothing for now
return FALSE;
}
return TRUE;
}
SetupImage::SetupImage(HDC hdc, HBITMAP bitmapSource, INT maxColors)
: ref(1), bitmap(NULL), pixels(NULL),
table(NULL), tableSize(0), tableCount(0), insertCursor(0), readCursor(0)
{
ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
BITMAP bm;
if (sizeof(BITMAP) != GetObject(bitmapSource, sizeof(BITMAP), &bm))
return;
if (bm.bmHeight < 0)
bm.bmHeight = -bm.bmHeight;
header.biSize = sizeof(BITMAPINFOHEADER);
header.biCompression = BI_RGB;
header.biBitCount = 24;
header.biPlanes = 1;
header.biWidth = bm.bmWidth;
header.biHeight = -(bm.bmHeight * (maxColors + 1));
bitmap = CreateDIBSection(hdc, (LPBITMAPINFO)&header, DIB_RGB_COLORS, (void**)&pixels, NULL, 0);
if (NULL == bitmap)
return;
if (FALSE == SetupImage_CopyImage(hdc, bitmap, 0, 0, bm.bmWidth, bm.bmHeight, bitmapSource, 0, 0))
{
DeleteObject(bitmap);
bitmap = NULL;
return;
}
tableSize = maxColors;
table = (IMAGEINDEX*)calloc(tableSize, sizeof(IMAGEINDEX));
if (NULL == table)
{
DeleteObject(bitmap);
bitmap = NULL;
return;
}
}
SetupImage::~SetupImage()
{
if (NULL != bitmap)
{
DeleteObject(bitmap);
bitmap = NULL;
}
if (NULL != table)
{
free(table);
table = NULL;
}
}
SetupImage *SetupImage::CreateInstance(HDC hdc, HBITMAP bitmapSource, INT maxColors)
{
if (NULL == bitmapSource || maxColors < 1 || maxColors > 120)
return NULL;
SetupImage *instance = new SetupImage(hdc, bitmapSource, maxColors);
if (NULL == instance) return NULL;
if (NULL == instance->bitmap || NULL == instance->table)
{
instance->Release();
instance = NULL;
}
return instance;
}
SetupImage *SetupImage::CreateFromPluginBitmap(HDC hdc, LPCWSTR pszModuleName, LPCWSTR resourceName, INT maxColors)
{
SetupImage *instance = NULL;
WCHAR szPath[MAX_PATH] = {0};
if (0 != GetModuleFileName(WASABI_API_ORIG_HINST, szPath, ARRAYSIZE(szPath)))
{
PathRemoveFileSpec(szPath);
PathAppend(szPath, pszModuleName);
HMODULE hModule = LoadLibraryEx(szPath, NULL, LOAD_LIBRARY_AS_DATAFILE | 0x00000020/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/);
if (NULL != hModule)
{
HBITMAP bitmapSource = (HBITMAP)LoadImage(hModule, resourceName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (NULL != bitmapSource)
instance = CreateInstance(hdc, bitmapSource, maxColors);
FreeLibrary(hModule);
}
}
return instance;
}
ULONG SetupImage::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupImage::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
BOOL SetupImage::GetSize(SIZE *pSize)
{
if (NULL == pSize) return FALSE;
INT cy = header.biHeight;
if (cy < 0) cy = -cy;
pSize->cx = header.biWidth;
pSize->cy = cy / (tableSize + 1);
return TRUE;
}
BOOL SetupImage::DrawImage(HDC hdc, INT x, INT y, INT cx, INT cy, INT srcX, INT srcY, COLORREF rgbBk, COLORREF rgbFg)
{
BYTE bitmapIndex = 0xFF;
SIZE imageSize;
if (!GetSize(&imageSize))
return FALSE;
for(BYTE i = readCursor; i < tableCount; i++)
{
if (table[i].rgbBk == rgbBk && table[i].rgbFg == rgbFg)
{
bitmapIndex = i;
break;
}
}
if (0xFF == bitmapIndex)
{
if (readCursor > tableCount)
readCursor = tableCount;
for(BYTE i = 0; i < readCursor; i++)
{
if (table[i].rgbBk == rgbBk && table[i].rgbFg == rgbFg)
{
bitmapIndex = i;
break;
}
}
if (0xFF == bitmapIndex)
{
if (tableCount < tableSize)
{
insertCursor = tableCount;
tableCount++;
}
else if (++insertCursor == tableCount)
insertCursor = 0;
INT targetY = (insertCursor + 1) * imageSize.cy;
if (!SetupImage_ColorizeImage(pixels, 0, 0, imageSize.cx, imageSize.cy,
header.biBitCount, 0, targetY, rgbBk, rgbFg, TRUE))
{
return FALSE;
}
table[insertCursor].rgbBk = rgbBk;
table[insertCursor].rgbFg = rgbFg;
bitmapIndex = insertCursor;
}
}
readCursor = bitmapIndex;
srcY += ((bitmapIndex + 1) * imageSize.cy);
INT dstY = y;
INT dstCY = cy;
INT imageHeight = header.biHeight;
if (imageHeight < 0)
{
header.biHeight = -imageHeight;
dstY += (cy - 1);
dstCY = -cy;
}
BOOL resultOk = StretchDIBits(hdc, x, dstY, cx, dstCY, srcX, srcY, cx, cy,
pixels, (BITMAPINFO*)&header, DIB_RGB_COLORS, SRCCOPY);
if (imageHeight < 0)
header.biHeight = imageHeight;
return resultOk;
}
BOOL SetupImage::ResetCache()
{
if (NULL != table)
ZeroMemory(&table, sizeof(IMAGEINDEX) * tableSize);
tableCount = 0;
insertCursor = 0;
readCursor = 0;
return TRUE;
}

View file

@ -0,0 +1,50 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <windows.h>
class SetupImage
{
private:
typedef struct __IMAGEINDEX
{
COLORREF rgbBk;
COLORREF rgbFg;
} IMAGEINDEX;
protected:
SetupImage(HDC hdc, HBITMAP bitmapSource, INT maxColors);
~SetupImage();
public:
static SetupImage *CreateInstance(HDC hdc, HBITMAP bitmapSource, INT maxColors);
static SetupImage *CreateFromPluginBitmap(HDC hdc, LPCWSTR pszModuleName, LPCWSTR resourceName, INT maxColors);
public:
ULONG AddRef();
ULONG Release();
BOOL GetSize(SIZE *pSize);
BOOL DrawImage(HDC hdc, INT x, INT y, INT cx, INT cy, INT srcX, INT srcY, COLORREF rgbBk, COLORREF rgbFg);
BOOL ResetCache();
private:
ULONG ref;
HBITMAP bitmap;
BYTE *pixels;
BITMAPINFOHEADER header;
IMAGEINDEX *table;
BYTE tableSize;
BYTE tableCount;
BYTE insertCursor;
BYTE readCursor;
};
#endif // NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER

View file

@ -0,0 +1,878 @@
#include "./setupPage.h"
#include "./setupListbox.h"
#include "./setupGroupList.h"
#include "./setupImage.h"
#include "../common.h"
#include "../resource.h"
#include "../api__ml_online.h"
#include "../../nu/windowsTheme.h"
#include <vssym32.h>
//#include <tmschema.h>
static ATOM SERVICELIST_PROP = 0;
#define SLF_UNICODE 0x0001
#define SLF_DRAGMOVE 0x0002
typedef BOOL (SetupListboxItem::*ITEMMOUSEPROC)(SetupListbox*, const RECT*, UINT, POINT);
class Listbox : public SetupListbox
{
protected:
Listbox(HWND hListbox, SetupGroupList *groupList);
~Listbox();
public:
static HRESULT AttachToWindow(HWND hwndListbox, SetupGroupList *groupList, SetupListbox **pInstance);
public:
HWND GetHwnd() { return hwnd; }
HFONT GetFont() { return (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0L); }
LRESULT CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL MeasureItem(INT itemId, UINT *cx, UINT *cy);
BOOL DrawItem(HDC hdc, const RECT *itemRect, INT itemId, UINT itemState, UINT itemAction);
INT_PTR KeyToItem(INT vKey, INT caretPos);
INT_PTR CharToItem(INT vKey, INT caretPos);
BOOL DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect);
BOOL GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize);
INT GetCheckboxThemeState(BOOL checked, UINT state);
INT HitTest(POINT pt, RECT *prcItem);
void SetCapture(SetupListboxItem *item);
SetupListboxItem *GetCapture();
void ReleaseCapture();
BOOL InvalidateRect(const RECT *prcInvalidate, BOOL fErase);
BOOL InvalidateItem(INT itemId, BOOL fErase);
void UpdateCount();
BOOL DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg);
BOOL GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize);
INT GetPageCount();
INT GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut);
INT GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut);
SetupListboxItem *GetSelection();
BOOL SetSelection(SetupListboxItem *item);
BOOL GetIndex(SetupListboxItem *item, INT *iItem);
BOOL DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt);
HMENU GetContextMenu(UINT menuId);
protected:
friend static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnDestroy();
void GetItemRect(INT itemId, RECT *prcItem);
SetupImage *GetExpandboxImage(HDC hdc, BOOL fExpanded);
void OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc);
void OnMouseLeave();
void OnEraseBkGround(HDC hdc);
void OnCaptureChanged(HWND hwndGained);
void NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain);
void OnCommand(INT commandId, INT eventId, HWND hControl);
protected:
HWND hwnd;
UINT flags;
WNDPROC originalProc;
UXTHEME buttonTheme;
SetupGroupList *groups;
INT mouseoverId;
INT capturedId;
SetupImage *expandedImage;
SetupImage *collapsedImage;
};
#define GetList(__hwnd) ((Listbox*)GetPropW((__hwnd), MAKEINTATOM(SERVICELIST_PROP)))
HRESULT SetupListbox::CreateInstance(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance)
{
return Listbox::AttachToWindow(hListbox, groupList, pInstance);
}
SetupListbox *SetupListbox::GetInstance(HWND hListbox)
{
return GetList(hListbox);
}
Listbox::Listbox(HWND hListbox, SetupGroupList *groupList)
: hwnd(hListbox), flags(0), originalProc(NULL), buttonTheme(NULL), groups(groupList),
mouseoverId(LB_ERR), capturedId(LB_ERR), expandedImage(NULL), collapsedImage(NULL)
{
if (IsWindowUnicode(hwnd))
flags |= SLF_UNICODE;
buttonTheme = (UxIsAppThemed()) ? UxOpenThemeData(hwnd, L"Button") : NULL;
groups->AddRef();
UpdateCount();
}
Listbox::~Listbox()
{
if (NULL != hwnd)
{
RemoveProp(hwnd, MAKEINTATOM(SERVICELIST_PROP));
if (NULL != originalProc)
{
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)originalProc);
CallPrevProc(WM_DESTROY, 0, 0L);
}
}
if (NULL != groups)
groups->Release();
if (NULL != buttonTheme)
UxCloseThemeData(buttonTheme);
if (NULL != expandedImage)
expandedImage->Release();
if (NULL != collapsedImage)
collapsedImage->Release();
}
HRESULT Listbox::AttachToWindow(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance)
{
if (0 == SERVICELIST_PROP)
{
SERVICELIST_PROP = GlobalAddAtom(TEXT("omSetupListbox"));
if (0 == SERVICELIST_PROP) return E_UNEXPECTED;
}
if(NULL == hListbox || !IsWindow(hListbox) || NULL == groupList)
return E_INVALIDARG;
Listbox *list = new Listbox(hListbox, groupList);
if (NULL == list)
return E_OUTOFMEMORY;
list->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hListbox, GWLP_WNDPROC,
(LONGX86)(LONG_PTR)Listbox_WindowProc);
if (NULL == list->originalProc || !SetProp(hListbox, MAKEINTATOM(SERVICELIST_PROP), list))
{
if (NULL != list->originalProc)
SetWindowLongPtr(hListbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)list->originalProc);
delete(list);
return E_FAIL;
}
if (NULL != pInstance)
*pInstance = list;
return S_OK;
}
LRESULT Listbox::CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return (0 != (SLF_UNICODE & flags)) ?
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
LRESULT Listbox::CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return (0 != (SLF_UNICODE & flags)) ?
CallWindowProcW(originalProc, hwnd, uMsg, wParam, lParam) :
CallWindowProcA(originalProc, hwnd, uMsg, wParam, lParam);
}
void Listbox::UpdateCount()
{
SendMessage(hwnd, WM_SETREDRAW, FALSE, 0L);
INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L);
size_t recordCount = (NULL != groups) ? groups->GetListboxCount() : 0;
SendMessage(hwnd, LB_SETCOUNT, (WPARAM)recordCount, 0L);
SetupListboxItem *item;
UINT cy, maxCY = 0;
for (size_t i = 0; i < recordCount; i++)
{
if (SUCCEEDED(groups->FindListboxItem(i, &item)) &&
item->MeasureItem(this, NULL, &cy) && cy > maxCY)
{
maxCY = cy;
}
}
SendMessage(hwnd, LB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)maxCY);
if (recordCount > 0)
{
if (iSelected < 0)
iSelected = 0;
if ((size_t)iSelected >= recordCount)
iSelected = (INT)(recordCount - 1);
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iSelected, TRUE);
SendMessage(hwnd, LB_SETANCHORINDEX, (WPARAM)iSelected, 0L);
SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iSelected, 0L);
}
SendMessage(hwnd, WM_SETREDRAW, TRUE, 0L);
}
BOOL Listbox::MeasureItem(INT itemId, UINT *cx, UINT *cy)
{
SetupListboxItem *item;
HRESULT hr = groups->FindListboxItem(itemId, &item);
return (SUCCEEDED(hr)) ? item->MeasureItem(this, cx, cy) : FALSE;
}
BOOL Listbox::DrawItem(HDC hdc, const RECT *prcItem, INT itemId, UINT itemState, UINT itemAction)
{
SetupListboxItem *item;
HRESULT hr = groups->FindListboxItem(itemId, &item);
if (FAILED(hr)) return FALSE;
if (0 != (ODS_SELECTED & itemState) && GetFocus() != hwnd)
itemState |= ODS_INACTIVE;
if (item->IsDisabled())
itemState |= ODS_DISABLED;
return item->DrawItem(this, hdc, prcItem, itemState);
}
INT Listbox::GetPageCount()
{
RECT clientRect;
if (NULL == hwnd || !GetClientRect(hwnd, &clientRect))
return 0;
INT itemHeight = (INT)SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0L);
return (clientRect.bottom - clientRect.top) / itemHeight;
}
INT Listbox::GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut)
{
INT iLast = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
if (iLast >= 0) iLast--;
SetupListboxItem *testItem;
while(iItem++ < iLast)
{
if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem)))
{
if (FALSE == testItem->IsDisabled()) break;
}
}
if (NULL != itemOut)
{
*itemOut = (iItem <= iLast) ? testItem : NULL;
}
return (iItem <= iLast) ? iItem : LB_ERR;
}
INT Listbox::GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut)
{
SetupListboxItem *testItem;
while(iItem-- > 0)
{
if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem)))
{
if (FALSE == testItem->IsDisabled()) break;
}
}
if (NULL != itemOut)
{
*itemOut = (iItem >= 0) ? testItem : NULL;
}
return (iItem >= 0) ? iItem : LB_ERR;
}
SetupListboxItem *Listbox::GetSelection()
{
INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L);
if (LB_ERR == iSelected)
return NULL;
SetupListboxItem *item;
return (SUCCEEDED(groups->FindListboxItem(iSelected, &item))) ? item : NULL;
}
BOOL Listbox::SetSelection(SetupListboxItem *item)
{
INT iItem = LB_ERR;
if (NULL != item)
{
iItem = groups->GetListboxItem(item);
if (LB_ERR == iItem)
return FALSE;
}
BOOL resultOk = (LB_ERR != SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iItem, 0L));
if (LB_ERR == iItem) resultOk = TRUE;
if (LB_ERR != iItem)
{
HWND hParent = GetParent(hwnd);
if (NULL != hParent)
SendMessage(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SELCHANGE), (LPARAM)hwnd);
}
return resultOk;
}
BOOL Listbox::GetIndex(SetupListboxItem *item, INT *iItem)
{
if (NULL == iItem)
return FALSE;
*iItem = (NULL != item && NULL != groups) ? groups->GetListboxItem(item) : LB_ERR;
return (LB_ERR != *iItem);
}
INT_PTR Listbox::KeyToItem(INT vKey, INT iCaret)
{
SetupListboxItem *item;
HRESULT hr = groups->FindListboxItem(iCaret, &item);
if (FAILED(hr)) return -1;
RECT itemRect;
GetItemRect(iCaret, &itemRect);
INT_PTR result = item->KeyToItem(this, &itemRect, vKey);
if (-1 != result) return result;
INT iTarget, iCount;
switch(vKey)
{
case VK_UP:
case VK_LEFT:
iTarget = GetPrevEnabledItem(iCaret, NULL);
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
return -2;
case VK_DOWN:
case VK_RIGHT:
iTarget = GetNextEnabledItem(iCaret, NULL);
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)iCaret, 0L);
return -2;
case VK_HOME:
if (iCaret > 0)
{
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
iTarget = GetNextEnabledItem(-1, NULL);
if (iTarget >= iCaret) iTarget = LB_ERR;
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
}
return -2;
case VK_PRIOR:
if (iCaret > 0)
{
INT iTop = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L);
if (iTop == iCaret)
{
INT iPage = iCaret - GetPageCount() + 1;
iTop = (iPage <= 0) ? 0 : (iPage - 1);
}
iTarget = GetPrevEnabledItem(iTop + 1, NULL);
if (LB_ERR == iTarget)
{
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
iTarget = GetNextEnabledItem(iTop, NULL);
if (iTarget > iCaret) iTarget = LB_ERR;
}
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
}
return -2;
case VK_END:
iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
if (iCount > 0 && iCaret != (iCount - 1))
{
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L);
iTarget = GetPrevEnabledItem(iCount, NULL);
if (iTarget <= iCaret) iTarget = LB_ERR;
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
}
return -2;
case VK_NEXT:
iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
if (iCount > 0 && iCaret != (iCount - 1))
{
INT iPage = GetPageCount();
INT iBottom = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L) + iPage - 1;
if (iBottom == iCaret)
{
iBottom += iPage;
if (iBottom >= iCount) iBottom = iCount -1;
}
iTarget = GetNextEnabledItem(iBottom - 1, NULL);
if (LB_ERR == iTarget)
{
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L);
iTarget = GetPrevEnabledItem(iBottom, NULL);
if (iTarget < iCaret) iTarget = LB_ERR;
}
if (LB_ERR != iTarget) return iTarget;
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
}
return -2;
}
return result;
}
INT_PTR Listbox::CharToItem(INT vKey, INT caretPos)
{
return -2;
//SetupListboxItem *item;
//HRESULT hr = groups->FindListboxItem(caretPos, &item);
//return (SUCCEEDED(hr)) ? item->CharToItem(this, vKey) : -1;
}
INT Listbox::GetCheckboxThemeState(BOOL checked, UINT state)
{
if (FALSE != checked)
{
if (0 != (ODS_DISABLED & state)) return CBS_CHECKEDDISABLED;
if (0 != (ODS_HOTLIGHT & state)) return CBS_CHECKEDHOT;
if (0 != (ODS_SELECTED & state)) return CBS_CHECKEDPRESSED;
return CBS_CHECKEDNORMAL;
}
if (0 != (ODS_DISABLED & state)) return CBS_UNCHECKEDDISABLED;
if (0 != (ODS_HOTLIGHT & state)) return CBS_UNCHECKEDHOT;
if (0 != (ODS_SELECTED & state)) return CBS_UNCHECKEDPRESSED;
return CBS_UNCHECKEDNORMAL;
}
BOOL Listbox::DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect)
{
if (NULL != buttonTheme)
{
INT stateId = GetCheckboxThemeState(checked, state);
if (SUCCEEDED(UxDrawThemeBackground(buttonTheme, hdc, BP_CHECKBOX, stateId, pRect, pClipRect)))
return TRUE;
}
UINT stateId = DFCS_BUTTONCHECK;
if (FALSE != checked) stateId |= DFCS_CHECKED;
if (0 != (ODS_DISABLED & state)) stateId |= DFCS_INACTIVE;
if (0 != (ODS_HOTLIGHT & state)) stateId |= DFCS_HOT;
if (0 != (ODS_SELECTED & state)) stateId |= DFCS_PUSHED;
return DrawFrameControl(hdc, (LPRECT)pRect,DFC_BUTTON, stateId);
}
BOOL Listbox::GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize)
{
if (NULL != buttonTheme)
{
HDC hdcMine = NULL;
if (NULL == hdc)
{
hdcMine = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
hdc = hdcMine;
}
INT stateId = GetCheckboxThemeState(checked, state);
HRESULT hr = UxGetThemePartSize(buttonTheme, hdc, BP_CHECKBOX,
stateId, NULL, TS_DRAW, pSize);
if (NULL != hdcMine)
ReleaseDC(hwnd, hdcMine);
if (SUCCEEDED(hr)) return TRUE;
}
pSize->cx = 13;
pSize->cy = 13;
return TRUE;
}
void Listbox::OnDestroy()
{
delete(this);
}
INT Listbox::HitTest(POINT pt, RECT *prcItem)
{
RECT itemRect;
INT itemId = (INT)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELONG(pt.x, pt.y));
if (LB_ERR == itemId ||
LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect) ||
FALSE == PtInRect(&itemRect, pt))
{
return LB_ERR;
}
if (NULL != prcItem)
CopyRect(prcItem, &itemRect);
return itemId;
}
void Listbox::GetItemRect(INT itemId, RECT *prcItem)
{
if (LB_ERR == ::SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)prcItem))
SetRectEmpty(prcItem);
}
BOOL Listbox::DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt)
{
if (WM_MOUSEMOVE == mouseEvent &&
0 != ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) & mouseFlags))
{
flags |= SLF_DRAGMOVE;
}
else
{
flags &= ~SLF_DRAGMOVE;
}
return (0 != (SLF_DRAGMOVE & flags));
}
void Listbox::OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc)
{
POINT pt;
POINTSTOPOINT(pt, pts);
SetupListboxItem *item;
RECT itemRect;
if (LB_ERR != capturedId)
{
if (SUCCEEDED(groups->FindListboxItem(capturedId, &item)))
{
GetItemRect(capturedId, &itemRect);
if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt)))
{
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
}
return;
}
capturedId = LB_ERR;
}
if (DoDragAndDrop(mouseEvent, mouseFlags, pt))
return;
INT itemId = HitTest(pt, &itemRect);
if (mouseoverId != itemId)
{
if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item)))
{
RECT leaveRect;
GetItemRect(mouseoverId, &leaveRect);
item->MouseLeave(this, &leaveRect);
}
mouseoverId = itemId;
TRACKMOUSEEVENT tm;
tm.cbSize = sizeof(TRACKMOUSEEVENT);
tm.hwndTrack = hwnd;
tm.dwFlags = TME_LEAVE;
if (LB_ERR == mouseoverId)
tm.dwFlags |= TME_CANCEL;
TrackMouseEvent(&tm);
}
if (LB_ERR != mouseoverId)
{
if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item)))
{
BOOL callListbox = FALSE;
if (FALSE != item->IsDisabled())
{
switch(mouseEvent)
{
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case 0x020C /*WM_XBUTTONUP*/:
callListbox = TRUE;
break;
}
}
else
{
if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt)))
{
callListbox = TRUE;
}
}
if (FALSE != callListbox)
{
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
}
return;
}
}
if (FALSE != fDefaultHandler)
{
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
}
}
void Listbox::OnMouseLeave()
{
if (LB_ERR != mouseoverId)
{
SetupListboxItem *item;
INT itemId = mouseoverId;
mouseoverId = LB_ERR;
if (SUCCEEDED(groups->FindListboxItem(itemId, &item)))
{
RECT itemRect;
GetItemRect(itemId, &itemRect);
if (item->MouseLeave(this, &itemRect))
return;
}
}
CallPrevProc(WM_MOUSELEAVE, 0, 0L);
}
void Listbox::SetCapture(SetupListboxItem *item)
{
INT prevCapturedId = capturedId;
capturedId = (NULL != item) ? groups->GetListboxItem(item) : LB_ERR;
NotifyReleaseCapture(prevCapturedId, item);
if (LB_ERR != capturedId && ::GetCapture() != hwnd)
::SetCapture(hwnd);
}
SetupListboxItem *Listbox::GetCapture()
{
SetupListboxItem *capturedItem;
if (LB_ERR == capturedId || FAILED(groups->FindListboxItem(capturedId, &capturedItem)))
capturedItem = NULL;
return capturedItem;
}
void Listbox::ReleaseCapture()
{
if (LB_ERR != capturedId)
{
INT prevCapturedId = capturedId;
capturedId = LB_ERR;
NotifyReleaseCapture(prevCapturedId, NULL);
if (::GetCapture() == hwnd)
::ReleaseCapture();
}
}
void Listbox::NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain)
{
if (LB_ERR == itemId)
return;
SetupListboxItem *item;
if (SUCCEEDED(groups->FindListboxItem(itemId, &item)))
{
RECT itemRect;
GetItemRect(itemId, &itemRect);
item->CaptureChanged(this, &itemRect, itemGain);
}
}
void Listbox::OnCaptureChanged(HWND hwndGained)
{
if (hwnd != hwndGained && LB_ERR != capturedId)
{
INT prevCapturedId = capturedId;
capturedId = LB_ERR;
NotifyReleaseCapture(prevCapturedId, NULL);
}
}
BOOL Listbox::InvalidateRect(const RECT *prcInvalidate, BOOL fErase)
{
return ::InvalidateRect(hwnd, prcInvalidate, fErase);
}
BOOL Listbox::InvalidateItem(INT itemId, BOOL fErase)
{
if (itemId < 0) return FALSE;
RECT itemRect;
if (LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect))
return FALSE;
return ::InvalidateRect(hwnd, &itemRect, fErase);
}
void Listbox::OnEraseBkGround(HDC hdc)
{
INT iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
RECT clientRect, itemRect;
GetClientRect(hwnd, &clientRect);
if (iCount > 0 &&
LB_ERR != SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)(iCount - 1), (LPARAM)&itemRect))
{
clientRect.top = itemRect.top;
}
if (clientRect.top < clientRect.bottom)
{
HBRUSH hb = NULL;
HWND hParent = GetParent(hwnd);
if (NULL != hParent)
{
hb = (HBRUSH)SendMessage(hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc, (LPARAM)hwnd);
}
if (NULL == hb)
{
hb = GetSysColorBrush(COLOR_WINDOW);
}
FillRect(hdc, &clientRect, hb);
}
}
void Listbox::OnCommand(INT commandId, INT eventId, HWND hControl)
{
if (NULL == hControl)
{
SetupListboxItem *item = GetSelection();
if (NULL != item)
{
item->Command(this, commandId, eventId);
}
}
}
SetupImage *Listbox::GetExpandboxImage(HDC hdc, BOOL fExpanded)
{
if (fExpanded)
{
if (NULL == expandedImage)
expandedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(137), 3);
return expandedImage;
}
if (NULL == collapsedImage)
collapsedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(135), 3);
return collapsedImage;
}
BOOL Listbox::DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg)
{
SetupImage *image = GetExpandboxImage(hdc, fExpanded);
return (NULL != image) ?
image->DrawImage(hdc, pRect->left, pRect->top,
pRect->right - pRect->left, pRect->bottom- pRect->top,
0, 0, rgbBk, rgbFg)
: FALSE;
}
BOOL Listbox::GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize)
{
SetupImage *image = GetExpandboxImage(hdc, fExpanded);
return (NULL != image) ? image->GetSize(pSize) : FALSE;
}
HMENU Listbox::GetContextMenu(UINT menuId)
{
HMENU baseMenu = WASABI_API_LOADMENUW(IDR_SETUPMENU);
if (NULL == baseMenu)
return NULL;
switch(menuId)
{
case menuGroupContext:
return GetSubMenu(baseMenu, 0);
}
return NULL;
}
LRESULT Listbox::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
OnDestroy();
return 0;
case WM_MOUSEMOVE:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::MouseMove);
return 0;
case WM_LBUTTONDOWN:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDown);
return 0;
case WM_LBUTTONUP:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::LButtonUp);
return 0;
case WM_LBUTTONDBLCLK:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDblClk);
return 0;
case WM_RBUTTONDOWN:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::RButtonDown);
return 0;
case WM_RBUTTONUP:
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::RButtonUp);
return 0;
case WM_MOUSELEAVE:
OnMouseLeave();
return 0;
case WM_CAPTURECHANGED:
OnCaptureChanged((HWND)lParam);
break;
case WM_ERASEBKGND:
OnEraseBkGround((HDC)wParam);
return TRUE;
case WM_COMMAND:
OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
return 0;
}
return CallPrevProc(uMsg, wParam, lParam);
}
static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Listbox *list = GetList(hwnd);
if (NULL != list)
return list->WindowProc(uMsg, wParam, lParam);
return (IsWindowUnicode(hwnd)) ?
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

View file

@ -0,0 +1,84 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <windows.h>
class SetupGroupList;
class SetupListboxItem;
class __declspec(novtable) SetupListbox
{
public:
typedef enum
{
menuGroupContext = 0,
} contextMenu;
public:
static HRESULT CreateInstance(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance);
static SetupListbox *GetInstance(HWND hListbox);
public:
virtual HWND GetHwnd() = 0;
virtual HFONT GetFont() = 0;
virtual LRESULT CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
virtual LRESULT CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
virtual BOOL MeasureItem(INT itemId, UINT *cx, UINT *cy) = 0;
virtual BOOL DrawItem(HDC hdc, const RECT *prcItem, INT itemId, UINT itemState, UINT itemAction) = 0;
virtual INT_PTR KeyToItem(INT vKey, INT caretPos) = 0;
virtual INT_PTR CharToItem(INT vKey, INT caretPos) = 0;
virtual BOOL DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect) = 0;
virtual BOOL GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize) = 0;
virtual void SetCapture(SetupListboxItem *item) = 0;
virtual SetupListboxItem *GetCapture() = 0;
virtual void ReleaseCapture() = 0;
virtual BOOL InvalidateRect(const RECT *prcInvalidate, BOOL fErase) = 0;
virtual BOOL InvalidateItem(INT iItem, BOOL fErase) = 0;
virtual void UpdateCount() = 0;
virtual BOOL DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg) = 0;
virtual BOOL GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize) = 0;
virtual INT GetPageCount() = 0;
virtual INT GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut) = 0;
virtual INT GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut) = 0;
virtual SetupListboxItem *GetSelection() = 0;
virtual BOOL SetSelection(SetupListboxItem *item) = 0;
virtual BOOL GetIndex(SetupListboxItem *item, INT *iItem) = 0;
virtual HMENU GetContextMenu(UINT menuId) = 0;
};
class __declspec(novtable) SetupListboxItem
{
public:
virtual BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy) = 0;
virtual BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state) = 0;
virtual INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey) = 0;
virtual BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem) = 0;
virtual BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
virtual void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured) = 0;
virtual BOOL IsDisabled() = 0;
virtual void Command(SetupListbox *instance, INT commandId, INT eventId) = 0;
virtual HWND CreateDetailsView(HWND hParent) = 0;
virtual BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax) = 0;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER

View file

@ -0,0 +1,228 @@
#include "./setupListboxLabel.h"
#include "../api__ml_online.h"
#include "../common.h"
#include <shlwapi.h>
#include <strsafe.h>
#define LABEL_MARGINCX 0
#define LABEL_MARGINCY 1
#define TEXT_OFFSET_LEFT 2
#define TEXT_OFFSET_BOTTOM 2
#define TEXT_ALIGN (TA_CENTER | TA_BOTTOM)
SetupListboxLabel::SetupListboxLabel(LPCWSTR pszName)
: ref(1), name(NULL)
{
SetName(pszName);
}
SetupListboxLabel::~SetupListboxLabel()
{
SetName(NULL);
}
SetupListboxLabel *SetupListboxLabel::CreateInstance(LPCWSTR pszName)
{
return new SetupListboxLabel(pszName);
}
ULONG SetupListboxLabel::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupListboxLabel::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT SetupListboxLabel::GetName(LPWSTR pszBuffer, INT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
if (NULL != name && IS_INTRESOURCE(name))
{
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)name, pszBuffer, cchBufferMax);
return (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
}
return StringCchCopyExW(pszBuffer, cchBufferMax, name, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT SetupListboxLabel::SetName(LPCWSTR pszName)
{
if (NULL != name && !IS_INTRESOURCE(name))
Plugin_FreeString(name);
if (IS_INTRESOURCE(pszName))
{
name = (LPWSTR)pszName;
}
else
{
name = Plugin_CopyString(pszName);
}
return S_OK;
}
BOOL SetupListboxLabel::IsNameNull()
{
return (NULL == name);
}
void SetupListboxLabel::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
{
COLORREF rgbBk, rgbText;
rgbBk = GetSysColor(COLOR_WINDOW);
rgbText = GetSysColor( (0 == (ODS_DISABLED & state)) ? COLOR_GRAYTEXT : COLOR_GRAYTEXT);
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
}
HBRUSH SetupListboxLabel::GetBrush(HDC hdc, UINT state)
{
return GetSysColorBrush(COLOR_WINDOW);
}
BOOL SetupListboxLabel::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
{
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return FALSE;
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
if (NULL != cy)
{
*cy = 0;
TEXTMETRIC tm;
if (GetTextMetrics(hdc, &tm))
*cy = tm.tmHeight + tm.tmExternalLeading + LABEL_MARGINCY*2;
}
if (NULL != cx)
{
*cx = 0;
WCHAR szBuffer[128] = {0};
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
{
INT cchBuffer = lstrlenW(szBuffer);
SIZE textSize;
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
{
*cx = textSize.cx + LABEL_MARGINCX*2;
}
}
}
SelectObject(hdc, originalFont);
ReleaseDC(instance->GetHwnd(), hdc);
return TRUE;
}
BOOL SetupListboxLabel::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
{
LONG paintLeft = prc->left + LABEL_MARGINCX;
COLORREF rgbBk, rgbText;
GetColors(hdc, state, &rgbBk, &rgbText);
COLORREF origBk = SetBkColor(hdc, rgbBk);
COLORREF origText = SetTextColor(hdc, rgbText);
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
HRGN backRgn, rgn;
backRgn = CreateRectRgnIndirect(prc);
rgn = CreateRectRgn(0,0,0,0);
RECT partRect;
WCHAR szBuffer[128] = {0};
INT cchBuffer = 0;
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
cchBuffer = lstrlenW(szBuffer);
SetRect(&partRect, paintLeft, prc->top, prc->right - LABEL_MARGINCX, prc->bottom);
if (ExtTextOut(hdc, partRect.left + (partRect.right - partRect.left)/2, partRect.bottom - TEXT_OFFSET_BOTTOM,
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
{
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
if (NULL != backRgn)
{
FillRgn(hdc, backRgn, GetBrush(hdc, state));
DeleteObject(backRgn);
}
if (NULL != rgn)
DeleteObject(rgn);
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
DrawFocusRect(hdc, prc);
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
if (origBk != rgbBk) SetBkColor(hdc, origBk);
if (origText != rgbText) SetTextColor(hdc, origText);
return TRUE;
}
INT_PTR SetupListboxLabel::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
{
return -1;
}
BOOL SetupListboxLabel::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupListboxLabel::MouseLeave(SetupListbox *instance, const RECT *prcItem)
{
return FALSE;
}
BOOL SetupListboxLabel::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupListboxLabel::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupListboxLabel::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupListboxLabel::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupListboxLabel::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
void SetupListboxLabel::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
{
}
BOOL SetupListboxLabel::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
{
WCHAR szName[128] = {0};
if (FAILED(GetName(szName, ARRAYSIZE(szName))))
return FALSE;
if (NULL == pszBuffer ||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"lbl_empty_%s", szName)))
{
return FALSE;
}
return TRUE;
}

View file

@ -0,0 +1,57 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./setupListbox.h"
class SetupListboxLabel: public SetupListboxItem
{
protected:
SetupListboxLabel(LPCWSTR pszName);
~SetupListboxLabel();
public:
static SetupListboxLabel *CreateInstance(LPCWSTR pszNamee);
public:
ULONG AddRef();
ULONG Release();
HRESULT GetName(LPWSTR pszBuffer, INT cchBufferMax);
HRESULT SetName(LPCWSTR pszName);
BOOL IsNameNull();
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
HBRUSH GetBrush(HDC hdc, UINT state);
/* SetupListboxItem */
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
BOOL IsDisabled() { return TRUE; }
void Command(SetupListbox *instance, INT commandId, INT eventId) {}
HWND CreateDetailsView(HWND hParent) { return NULL; }
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
protected:
ULONG ref;
LPWSTR name;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER

View file

@ -0,0 +1,395 @@
#include "./setupLog.h"
#include "../common.h"
#include "../api__ml_online.h"
#include "../config.h"
#include "../../nu/trace.h"
#include <ifc_omservice.h>
#include <ifc_omwebstorage.h>
#include <ifc_omstorageasync.h>
#include <shlwapi.h>
#include <strsafe.h>
#define SETUPLOG_SEPARATOR ','
#define SETUPLOG_SECTION "Setup"
#define SETUPLOG_KEY_SUBSCRIBED "subscribed"
#define SETUPLOG_KEY_UNSUBSCRIBED "unsubscribed"
struct LOGPARSERPARAM
{
LOGPARSERPARAM() : instance(NULL), operation(0) {}
SetupLog *instance;
UINT operation;
};
static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap)
{
SetupLog::ServiceMap::iterator it;
size_t c1 = 0, c2 = 0;
for (it = serviceMap->begin(); it != serviceMap->end(); it++)
{
switch(it->second)
{
case SetupLog::opServiceAdded:
c1++;
break;
case SetupLog::opServiceRemoved:
c2++;
break;
}
}
return (c1 > c2) ? c1 : c2;
}
static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax)
{
if (NULL == pszBuffer)
return E_INVALIDARG;
*pszBuffer = '\0';
if (NULL == serviceMap)
return S_OK;
HRESULT hr = S_OK;
size_t remaining = cchBufferMax;
LPSTR cursor = pszBuffer;
SetupLog::ServiceMap::iterator it;
const char format[] = { SETUPLOG_SEPARATOR, '%', 'u', '\0'};
for (it = serviceMap->begin(); it != serviceMap->end() && SUCCEEDED(hr); it++)
{
if (it->second == operation)
{
hr = StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
((cursor == pszBuffer) ? (format + 1) : format), it->first);
}
}
return hr;
}
static LPCSTR SetupLog_GetOperationKey(UINT operation)
{
switch(operation)
{
case SetupLog::opServiceAdded: return SETUPLOG_KEY_SUBSCRIBED;
case SetupLog::opServiceRemoved: return SETUPLOG_KEY_UNSUBSCRIBED;
}
return NULL;
}
static LPCWSTR SetupLog_GetOperationAction(UINT operation)
{
switch(operation)
{
case SetupLog::opServiceAdded: return L"add";
case SetupLog::opServiceRemoved: return L"remove";
}
return NULL;
}
static BOOL SetupLog_WriteOperationLog(UINT operation, LPCSTR pszValue)
{
LPCSTR pszKey = SetupLog_GetOperationKey(operation);
if (NULL == pszKey) return FALSE;
return Config_WriteStr(SETUPLOG_SECTION, pszKey, pszValue);
}
static HRESULT SetupLog_ReadOperationLog(UINT operation, LPSTR pszBuffer, UINT cchBufferMax, UINT *cchReaded)
{
LPCSTR pszKey = SetupLog_GetOperationKey(operation);
if (NULL == pszKey) return E_INVALIDARG;
DWORD readed = Config_ReadStr(SETUPLOG_SECTION, pszKey, NULL, pszBuffer, cchBufferMax);
if (NULL != cchReaded)
{
*cchReaded = readed;
}
return S_OK;
}
SetupLog::SetupLog() : ref(1)
{
}
SetupLog::~SetupLog()
{
}
SetupLog *SetupLog::Open()
{
SetupLog *instance = new SetupLog();
if (NULL == instance) return NULL;
INT cchBuffer = 32000;
LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);
if (NULL == buffer)
{
instance->Release();
return NULL;
}
UINT cchReaded = 0;
const UINT szOperations[] = { opServiceAdded,
opServiceRemoved, };
UINT serviceId;
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
{
if (SUCCEEDED(SetupLog_ReadOperationLog(szOperations[i], buffer, cchBuffer, &cchReaded)) && cchReaded > 0)
{
LPSTR cursor = buffer;
LPSTR block = cursor;
for(;;)
{
if (SETUPLOG_SEPARATOR == *cursor || '\0' == *cursor)
{
while (' ' == *block && block < cursor) block++;
if (block < cursor &&
FALSE != StrToIntExA(block, STIF_SUPPORT_HEX, (INT*)&serviceId) &&
0 != serviceId)
{
instance->LogServiceById(serviceId, szOperations[i]);
}
if ('\0' == *cursor)
break;
cursor++;
block = cursor;
}
else
{
cursor++;
}
}
}
}
Plugin_FreeAnsiString(buffer);
return instance;
}
ULONG SetupLog::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupLog::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
BOOL SetupLog::IsOperationSupported(UINT operation)
{
switch(operation)
{
case SetupLog::opServiceAdded:
case SetupLog::opServiceRemoved:
return TRUE;
}
return FALSE;
}
HRESULT SetupLog::LogServiceById(UINT serviceUid, UINT operation)
{
if (0 == serviceUid || FALSE == IsOperationSupported(operation))
return E_INVALIDARG;
serviceMap[serviceUid] = operation;
return S_OK;
}
HRESULT SetupLog::LogService(ifc_omservice *service, UINT operation)
{
if (NULL == service || !IsOperationSupported(operation))
return E_INVALIDARG;
return LogServiceById(service->GetId(), operation);
}
HRESULT SetupLog::Save()
{
LPSTR buffer = NULL;
size_t cchBuffer = SetupLog_GetMaxServiceIdCount(&serviceMap) * 11;
if (0 != cchBuffer)
{
cchBuffer += 1;
buffer = Plugin_MallocAnsiString(cchBuffer);
if (NULL == buffer)
return E_OUTOFMEMORY;
}
const UINT szOperations[] = { opServiceAdded,
opServiceRemoved, };
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
{
LPCSTR value = (NULL != buffer &&
SUCCEEDED(SetupLog_FormatServiceId(&serviceMap, szOperations[i], buffer, cchBuffer)) &&
'\0' != *buffer) ? buffer : NULL;
SetupLog_WriteOperationLog(szOperations[i], value);
}
if (NULL != buffer)
Plugin_FreeAnsiString(buffer);
return S_OK;
}
HRESULT SetupLog::Erase()
{
HRESULT hr = S_OK;
if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_SUBSCRIBED, NULL))
hr = E_FAIL;
if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_UNSUBSCRIBED, NULL))
hr = E_FAIL;
return hr;
}
struct LOGSENDJOBPARAM
{
LOGSENDJOBPARAM() : totalJobs(0), storage(NULL), completeEvent(NULL) {}
ULONG totalJobs;
CRITICAL_SECTION lock;
ifc_omstorage *storage;
HANDLE completeEvent;
};
static void CALLBACK SetupLog_SendCompleted(ifc_omstorageasync *async)
{
if (NULL != async)
{
LOGSENDJOBPARAM *param = NULL;
if (SUCCEEDED(async->GetData((void**)&param)) && NULL != param)
{
EnterCriticalSection(&param->lock);
if (NULL != param->storage)
{
param->storage->EndLoad(async, NULL);
param->storage->Release();
}
LONG r = InterlockedDecrement((LONG*)&param->totalJobs);
if (0 == r)
{
if (NULL != param->completeEvent)
SetEvent(param->completeEvent);
LeaveCriticalSection(&param->lock);
DeleteCriticalSection(&param->lock);
free(param);
param = NULL;
}
else
{
LeaveCriticalSection(&param->lock);
}
}
}
}
HRESULT SetupLog::Send(HANDLE completeEvent)
{
size_t cchAlloc = serviceMap.size();
if (0 == cchAlloc)
{
if (NULL != completeEvent) SetEvent(completeEvent);
return S_OK;
}
UINT *buffer = (UINT*)calloc(cchAlloc, sizeof(UINT));
LOGSENDJOBPARAM *param = (LOGSENDJOBPARAM*)calloc(1, sizeof(LOGSENDJOBPARAM));
if (NULL == buffer || NULL == param)
{
if (NULL != buffer) { free(buffer); buffer = NULL; }
if (NULL != param) { free(param); param = NULL; }
if (NULL != completeEvent) { SetEvent(completeEvent); completeEvent = NULL; }
return E_OUTOFMEMORY;
}
ifc_omstorage *storage = NULL;
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
if (SUCCEEDED(hr) && storage != NULL)
{
const UINT szOperations[] = { opServiceAdded,
opServiceRemoved, };
param->totalJobs = 0;
param->completeEvent = completeEvent;
param->storage = storage;
InitializeCriticalSection(&param->lock);
EnterCriticalSection(&param->lock);
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
{
size_t count = 0;
hr = S_OK;
for (SetupLog::ServiceMap::iterator it = serviceMap.begin(); it != serviceMap.end() && SUCCEEDED(hr); it++)
{
if (it->second == szOperations[i])
{
buffer[count] = it->first;
count++;
}
}
if (0 != count)
{
LPWSTR url = NULL;
LPCWSTR action = SetupLog_GetOperationAction(szOperations[i]);
if (NULL != action &&
SUCCEEDED(Plugin_BuildActionUrl(&url, action, buffer, count)))
{
ifc_omstorageasync *async = NULL;;
if (SUCCEEDED(storage->BeginLoad(url, NULL, SetupLog_SendCompleted, param, &async)))
{
InterlockedIncrement((LONG*)&param->totalJobs);
storage->AddRef();
async->Release();
}
Plugin_FreeString(url);
}
}
}
if (0 == param->totalJobs)
{
LeaveCriticalSection(&param->lock);
DeleteCriticalSection(&param->lock);
hr = E_FAIL;
if (param) { free(param); param = NULL; }
}
else
{
LeaveCriticalSection(&param->lock);
}
storage->Release();
}
if (buffer) { free(buffer); buffer = NULL; }
return hr;
}

View file

@ -0,0 +1,54 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <map>
class ifc_omservice;
class SetupLog
{
public:
typedef enum
{
opUnknown = 0,
opServiceAdded = 1,
opServiceRemoved = 2,
};
protected:
SetupLog();
~SetupLog();
public:
static SetupLog *Open();
static HRESULT Erase();
public:
ULONG AddRef();
ULONG Release();
HRESULT LogServiceById(UINT serviceUid, UINT operation);
HRESULT LogService(ifc_omservice *service, UINT operation);
HRESULT Save();
HRESULT Send(HANDLE completeEvent);
BOOL IsOperationSupported(UINT operation);
protected:
typedef std::map<UINT, UINT> ServiceMap;
friend static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap);
friend static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax);
protected:
ULONG ref;
ServiceMap serviceMap;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER

View file

@ -0,0 +1,648 @@
#include "./setupPage.h"
#include "./setupListbox.h"
#include "./setupGroupList.h"
#include "./setupGroupFilter.h"
#include "./setupListboxLabel.h"
#include "../common.h"
#include "../config.h"
#include "../resource.h"
#include "../api__ml_online.h"
#include "./setupDetails.h"
#include "./setupLog.h"
#include "../../winamp/setup/svc_setup.h"
#include <ifc_omservice.h>
#include <ifc_omfilestorage.h>
#include <ifc_omwebstorage.h>
#include <windows.h>
#include <strsafe.h>
#include <vector>
#define FEATURED_SERVICES_URL L"http://services.winamp.com/svc/default"
#define IDC_DETAILS 10000
typedef std::vector<ifc_omservice*> ServiceList;
typedef std::vector<UINT> ServiceIdList;
HWND SetupPage_CreateWindow(HWND hParent, SetupPage *page);
static INT_PTR SetupPage_ModalLoop(HWND hwnd, HACCEL hAccel, HANDLE hCancel);
struct AppendServiceToStringData
{
AppendServiceToStringData() : formatFirst(NULL), formatNext(NULL), cursor(NULL),
remaining(0), inserted(0), result(S_OK) {}
LPCWSTR formatFirst;
LPCWSTR formatNext;
LPWSTR cursor;
size_t remaining;
size_t inserted;
HRESULT result;
};
static BOOL CALLBACK SetupPage_AppendServiceToStringCallback(UINT serviceId, void *data)
{
AppendServiceToStringData *param = (AppendServiceToStringData*)data;
if (NULL == param) return FALSE;
param->result = StringCchPrintfEx(param->cursor, param->remaining, &param->cursor, &param->remaining,
STRSAFE_NULL_ON_FAILURE,
((0 == param->inserted) ? param->formatFirst : param->formatNext), serviceId);
if (FAILED(param->result))
return FALSE;
param->inserted++;
return TRUE;
}
static BOOL CALLBACK SetupPage_AppendServiceIdCallback(UINT serviceId, void *data)
{
ServiceIdList *list = (ServiceIdList*)data;
if (NULL == list) return FALSE;
list->push_back(serviceId);
return TRUE;
}
static HRESULT SetupPage_GetFeaturedServicesUrl(LPWSTR pszBuffer, UINT cchBufferMax)
{
LPWSTR cursor = pszBuffer;
size_t remaining = cchBufferMax;
HRESULT hr = StringCchCopyEx(cursor, remaining, FEATURED_SERVICES_URL, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
if (FAILED(hr))
return hr;
AppendServiceToStringData param;
param.cursor = cursor;
param.remaining = remaining;
param.formatFirst = L"?svc_ids=%u";
param.formatNext = L",%u";
param.inserted = 0;
param.result = S_OK;
hr = Config_ReadServiceIdList("Setup", "featuredExtra", ',', SetupPage_AppendServiceToStringCallback, &param);
if (SUCCEEDED(hr))
hr = param.result;
return hr;
}
SetupPage* SetupPage::CreateInstance()
{
SetupPage *instance = new SetupPage();
return instance;
}
SetupPage::SetupPage()
: ref(1), hwnd(NULL), name(NULL), title(NULL),
groupList(NULL), completeEvent(NULL),
servicesInitialized(FALSE)
{
WasabiApi_AddRef();
SetupDetails_Initialize();
}
SetupPage::~SetupPage()
{
if (NULL != name)
{
Plugin_FreeString(name);
name = NULL;
}
if (NULL != title)
{
Plugin_FreeString(title);
title = NULL;
}
if (NULL != groupList)
{
groupList->Release();
groupList = NULL;
}
if (NULL != completeEvent)
{
CloseHandle(completeEvent);
completeEvent = NULL;
}
SetupDetails_Uninitialize();
if (FALSE != servicesInitialized)
{
if (NULL != OMBROWSERMNGR)
OMBROWSERMNGR->Finish();
}
WasabiApi_Release();
}
size_t SetupPage::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t SetupPage::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int SetupPage::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
return E_NOTIMPL;
}
HRESULT SetupPage::GetName(bool bShort, const wchar_t **pszName)
{
InitializeServices();
if (false == bShort)
{
if (NULL == title)
{
WCHAR szBuffer[128] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_SETUPPAGE_TITLE, szBuffer, ARRAYSIZE(szBuffer));
title = Plugin_CopyString(szBuffer);
}
*pszName = title;
}
else
{
if (NULL == name)
{
WCHAR szBuffer[128] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_ONLINE_SERVICES, szBuffer, ARRAYSIZE(szBuffer));
name = Plugin_CopyString(szBuffer);
}
*pszName = name;
}
return S_OK;
}
HRESULT SetupPage::Save(HWND hwndText)
{
if (NULL == groupList)
return S_OK;
SetupLog *log = SetupLog::Open();
HRESULT hr = groupList->Save(log);
if (NULL != log)
{
log->Save();
log->Release();
}
return hr;
}
HRESULT SetupPage::Revert(void)
{
HRESULT hr(S_OK);
if (NULL != groupList)
{
groupList->Release();
groupList = NULL;
}
return hr;
}
HRESULT SetupPage::IsDirty(void)
{
return (NULL != groupList && groupList->IsModified()) ? S_OK : S_FALSE;
}
HRESULT SetupPage::Validate(void)
{
return S_OK;
}
HRESULT SetupPage::InitializeServices()
{
if (FALSE != servicesInitialized)
return S_FALSE;
HWND hWinamp = NULL;
svc_setup *setupSvc = QueryWasabiInterface(svc_setup, UID_SVC_SETUP);
if (NULL == setupSvc) return E_UNEXPECTED;
HRESULT hr = setupSvc->GetWinampWnd(&hWinamp);
ReleaseWasabiInterface(UID_SVC_SETUP, setupSvc);
if (SUCCEEDED(hr))
{
hr = WasabiApi_LoadDefaults();
if (SUCCEEDED(hr))
{
if (NULL != OMBROWSERMNGR &&
NULL != OMSERVICEMNGR &&
NULL != OMUTILITY)
{
hr = OMBROWSERMNGR->Initialize(NULL, hWinamp);
}
else
hr = E_UNEXPECTED;
if (SUCCEEDED(hr))
servicesInitialized = TRUE;
}
}
return hr;
}
HRESULT SetupPage::CreateView(HWND hParent, HWND *phwnd)
{
if (NULL == phwnd)
return E_INVALIDARG;
if (FAILED(InitializeServices()))
{
*phwnd = NULL;
return E_FAIL;
}
*phwnd = SetupPage_CreateWindow(hParent, this);
return (NULL == phwnd) ? E_FAIL : S_OK;
}
BOOL SetupPage::UpdateListAsync(INT groupId)
{
if (NULL == hwnd)
return FALSE;
return PostMessage(hwnd, SPM_UPDATELIST, (WPARAM)groupId, NULL);
}
BOOL SetupPage::AttachWindow(HWND hAttach)
{
hwnd = hAttach;
if (NULL == completeEvent)
completeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == groupList)
{
groupList = SetupGroupList::CreateInstance();
if (NULL != groupList)
{
WCHAR szBuffer[4096] = {0};
SetupPage_GetFeaturedServicesUrl(szBuffer, ARRAYSIZE(szBuffer));
SetupGroup *group = SetupGroup::CreateInstance(ID_FEATUREDGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED),
szBuffer, &SUID_OmStorageUrl, &FUID_SetupFeaturedGroupFilter,
SetupGroup::styleSortAlphabetically | SetupGroup::styleDefaultSubscribed | SetupGroup::styleSaveAll);
if (NULL != group)
{
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATUREDLONG));
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED_DESC));
groupList->AddGroup(group);
group->RequestReload();
group->Release();
}
group = SetupGroup::CreateInstance(ID_KNOWNGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN),
L"*.ini", &SUID_OmStorageIni, &FUID_SetupKnownGroupFilter,
SetupGroup::styleSortAlphabetically);
if (NULL != group)
{
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWNLONG));
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN_DESC));
group->RequestReload();
groupList->AddGroup(group);
group->Release();
}
}
}
if (NULL != groupList)
groupList->SetPageWnd(hwnd);
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
if (NULL != hList)
{
SetupListbox *listbox;
if (SUCCEEDED(SetupListbox::CreateInstance(hList, groupList, &listbox)))
{
}
ListboxSelectionChanged();
}
return TRUE;
}
void SetupPage::DetachWindow()
{
hwnd = NULL;
if (NULL != groupList)
{
groupList->SetPageWnd(NULL);
}
}
HRESULT SetupPage_AppendUnselectedServices(LPCSTR pszSection, LPCSTR pszKey, SetupGroup *group)
{
size_t index = group->GetRecordCount();
size_t filterIndex, filterSize;
ServiceIdList list;
Config_ReadServiceIdList(pszSection, pszKey, ',', SetupPage_AppendServiceIdCallback, &list);
filterSize = list.size();
while(index--)
{
SetupRecord *record = group->GetRecord(index);
if (NULL == record || FALSE != record->IsSelected()) continue;
ifc_omservice *service = record->GetService();
if (NULL == service) continue;
UINT serviceId = service->GetId();
for(filterIndex = 0; filterIndex < filterSize; filterIndex++)
{
if (list[filterIndex] == serviceId)
break;
}
if (filterIndex == filterSize)
list.push_back(serviceId);
}
if (0 != list.size())
{
size_t bufferAlloc = (list.size() * 11) * sizeof(CHAR);
LPSTR buffer = Plugin_MallocAnsiString(bufferAlloc);
if (NULL != buffer)
{
filterSize = list.size();
LPSTR cursor = buffer;
size_t remaining = bufferAlloc;
for(index = 0; index < filterSize; index++)
{
if (FAILED(StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
((0 == index) ? "%u" : ",%u"), list[index])))
{
break;
}
}
Config_WriteStr(pszSection, pszKey, buffer);
Plugin_FreeAnsiString(buffer);
}
}
else
Config_WriteStr(pszSection, pszKey, NULL);
return S_OK;
}
HRESULT SetupPage::Execute(HWND hwndText)
{
SetupGroup *group = NULL;
SetupLog *log = SetupLog::Open();
WCHAR szBuffer[128] = {0};
if (FAILED(InitializeServices()))
return E_FAIL;
if (NULL == groupList)
{
groupList = SetupGroupList::CreateInstance();
if (NULL == groupList) return E_UNEXPECTED;
}
if (S_OK != groupList->FindGroupById(ID_FEATUREDGROUP, &group) && group != NULL)
{
WCHAR szBuffer[4096] = {0};
SetupPage_GetFeaturedServicesUrl(szBuffer, ARRAYSIZE(szBuffer));
group = SetupGroup::CreateInstance(ID_FEATUREDGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED),
szBuffer, &SUID_OmStorageUrl, &FUID_SetupFeaturedGroupFilter,
SetupGroup::styleDefaultSubscribed | SetupGroup::styleSaveAll);
if (NULL != group)
{
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATUREDLONG));
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED_DESC));
groupList->AddGroup(group);
group->RequestReload();
}
}
if (NULL == completeEvent)
completeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL != group)
{
if (SUCCEEDED(group->SignalLoadCompleted(completeEvent)))
{
WASABI_API_LNGSTRINGW_BUF(IDS_DOWNLOADSERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
SetWindowText(hwndText, szBuffer);
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
}
WASABI_API_LNGSTRINGW_BUF(IDS_SAVESERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
SetWindowText(hwndText, szBuffer);
group->Save(log);
SetupPage_AppendUnselectedServices("Setup", "featuredHistory", group);
group->Release();
group = NULL;
}
// ensure that promotions are subscribed
if (S_OK != groupList->FindGroupById(ID_KNOWNGROUP, &group) && group != NULL)
{
group = SetupGroup::CreateInstance(ID_KNOWNGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN),
L"*.ini", &SUID_OmStorageIni, &FUID_SetupKnownGroupFilter,
SetupGroup::styleSortAlphabetically);
if (NULL != group)
{
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWNLONG));
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN_DESC));
group->RequestReload();
groupList->AddGroup(group);
}
}
if (NULL != group)
{
WASABI_API_LNGSTRINGW_BUF(IDS_SAVESERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
SetWindowText(hwndText, szBuffer);
ResetEvent(completeEvent);
if (SUCCEEDED(group->SignalLoadCompleted(completeEvent)))
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
group->Save(log);
group->Release();
group = NULL;
}
if (NULL != log)
{
WASABI_API_LNGSTRINGW_BUF(IDS_REGISTERINGSERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
SetWindowText(hwndText, szBuffer);
ResetEvent(completeEvent);
log->Send(completeEvent);
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
log->Release();
}
SetupLog::Erase();
Config_WriteStr("Setup", "featuredExtra", NULL); // delete promo offer
return S_OK;
}
HRESULT SetupPage::Cancel(HWND hwndText)
{
if (NULL != completeEvent)
SetEvent(completeEvent);
return S_OK;
}
HRESULT SetupPage::IsCancelSupported(void)
{
return S_OK;
}
void SetupPage::ListboxSelectionChanged()
{
if (NULL == hwnd) return;
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
if (NULL == hList) return;
SetupListboxItem *item = NULL;
INT iSelection = (INT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
if (LB_ERR == iSelection ||
FAILED(groupList->FindListboxItem(iSelection, &item)))
{
item = NULL;
}
HWND hDiscard = GetDlgItem(hwnd, IDC_DETAILS);
if (NULL != hDiscard)
{
WCHAR szPanel[64] = {0}, szItem[64] = {0};
if (FALSE != SetupDetails_GetUniqueName(hDiscard, szPanel, ARRAYSIZE(szPanel)) &&
FALSE != item->GetUniqueName(szItem, ARRAYSIZE(szItem)) &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, szPanel, - 1, szItem, -1))
{
return;
}
}
HWND hDetails = (NULL != item) ? item->CreateDetailsView(hwnd) : NULL;
if (NULL != hDiscard)
{
SetWindowLongPtr(hDiscard, GWL_STYLE, GetWindowLongPtr(hDiscard, GWL_STYLE) & ~WS_VISIBLE);
}
if (NULL != hDetails)
{
HWND hPlaceholder = GetDlgItem(hwnd, IDC_PLACEHOLDER);
if (NULL != hPlaceholder)
{
RECT windowRect;
if (GetWindowRect(hPlaceholder, &windowRect))
{
MapWindowPoints(HWND_DESKTOP,hwnd, (POINT*)&windowRect,2);
SetWindowPos(hDetails, NULL, windowRect.left, windowRect.top,
windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
SetWindowLongPtr(hDetails, GWLP_ID, IDC_DETAILS);
ShowWindow(hDetails, SW_SHOWNA);
RedrawWindow(hDetails, NULL, NULL, RDW_ERASENOW |RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}
if (NULL != hDiscard)
{
DestroyWindow(hDiscard);
}
}
static INT_PTR SetupPage_ModalLoop(HWND hwnd, HACCEL hAccel, HANDLE hCancel)
{
MSG msg = {0};
HWND hParent = NULL;
while (NULL != (hParent = GetAncestor(hwnd, GA_PARENT)))
{
hwnd = hParent;
}
if (NULL == hwnd)
return 0;
for (;;)
{
DWORD status = MsgWaitForMultipleObjectsEx(1, &hCancel, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
if (WAIT_OBJECT_0 == status)
{
return 0;
}
else if ((WAIT_OBJECT_0 + 1)== status)
{
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
//if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
{
if (msg.message == WM_QUIT)
{
PostQuitMessage((INT)msg.wParam);
return msg.wParam;
}
if (!TranslateAcceleratorW(hwnd, hAccel, &msg) &&
!IsDialogMessageW(hwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
}
}
return 0;
}
#define CBCLASS SetupPage
START_MULTIPATCH;
START_PATCH(MPIID_SETUPPAGE)
M_CB(MPIID_SETUPPAGE, ifc_setuppage, ADDREF, AddRef);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, RELEASE, Release);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, QUERYINTERFACE, QueryInterface);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_GET_NAME, GetName);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_CREATEVIEW, CreateView);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_SAVE, Save);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_REVERT, Revert);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_ISDIRTY, IsDirty);
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_VALIDATE, Validate);
NEXT_PATCH(MPIID_SETUPJOB)
M_CB(MPIID_SETUPJOB, ifc_setupjob, ADDREF, AddRef);
M_CB(MPIID_SETUPJOB, ifc_setupjob, RELEASE, Release);
M_CB(MPIID_SETUPJOB, ifc_setupjob, QUERYINTERFACE, QueryInterface);
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_EXECUTE, Execute);
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_CANCEL, Cancel);
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_ISCANCELSUPPORTED, IsCancelSupported);
END_PATCH
END_MULTIPATCH;
#undef CBCLASS

View file

@ -0,0 +1,85 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <bfc/multipatch.h>
#include "../../winamp/setup/ifc_setuppage.h"
#include "../../winamp/setup/ifc_setupjob.h"
#include "./setupGroupList.h"
class SetupListboxLabel;
#define ID_KNOWNGROUP 0
#define ID_FEATUREDGROUP 1
#define MPIID_SETUPPAGE 10
#define MPIID_SETUPJOB 20
#define SPM_FIRST (WM_APP + 2)
#define SPM_UPDATELIST (SPM_FIRST + 0)
class SetupPage : public MultiPatch<MPIID_SETUPPAGE, ifc_setuppage>,
public MultiPatch<MPIID_SETUPJOB, ifc_setupjob>
{
protected:
typedef enum
{
flagInitWasabi = 0x00000001,
};
protected:
SetupPage();
virtual ~SetupPage();
public:
static SetupPage* CreateInstance();
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_setuppage */
HRESULT GetName(bool bShort, const wchar_t **pszName);
HRESULT Save(HWND hText);
HRESULT CreateView(HWND hParent, HWND *phwnd);
HRESULT Revert(void);
HRESULT IsDirty(void);
HRESULT Validate(void);
/* ifc_setupjob */
HRESULT Execute(HWND hwndText);
HRESULT Cancel(HWND hwndText);
HRESULT IsCancelSupported(void);
public:
BOOL AttachWindow(HWND hAttach);
void DetachWindow();
void ListboxSelectionChanged();
BOOL UpdateListAsync(INT groupId);
protected:
HRESULT InitializeServices();
private:
size_t ref;
HWND hwnd;
LPWSTR name;
LPWSTR title;
SetupGroupList *groupList;
HANDLE completeEvent;
BOOL servicesInitialized;
protected:
RECVS_MULTIPATCH;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER

View file

@ -0,0 +1,145 @@
#include "./setupPage.h"
#include "./setupListbox.h"
#include "../common.h"
#include "../resource.h"
#include "../api__ml_online.h"
static ATOM SETUPPAGE_PROP = 0;
#define GetPage(__hwnd) ((SetupPage*)GetPropW((__hwnd), MAKEINTATOM(SETUPPAGE_PROP)))
static INT_PTR WINAPI SetupPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND SetupPage_CreateWindow(HWND hParent, SetupPage *page)
{
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUPPAGE, hParent, SetupPage_DialogProc, (LPARAM)page);
}
static INT_PTR SetupPage_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
{
if (0 == SETUPPAGE_PROP)
{
SETUPPAGE_PROP = GlobalAddAtom(L"omSetupPageProp");
if (0 == SETUPPAGE_PROP) return FALSE;
}
SetupPage *page = (SetupPage*)lParam;
if (NULL != page && page->AttachWindow(hwnd))
{
SetProp(hwnd, MAKEINTATOM(SETUPPAGE_PROP), page);
}
return FALSE;
}
static void SetupPage_OnDestroy(HWND hwnd)
{
SetupPage *page = GetPage(hwnd);
if (NULL != page)
{
page->DetachWindow();
}
RemoveProp(hwnd, MAKEINTATOM(SETUPPAGE_PROP));
}
static void SetupPage_OnCommand(HWND hwnd, INT controlId, INT eventId, HWND hControl)
{
SetupPage *page;
switch(controlId)
{
case IDC_SERVICELIST:
switch(eventId)
{
case LBN_SELCHANGE:
page = GetPage(hwnd);
if (NULL != page)
page->ListboxSelectionChanged();
break;
}
break;
}
}
static BOOL SetupPage_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *pmis)
{
SetupListbox *instance;
switch(pmis->CtlID)
{
case IDC_SERVICELIST:
instance = SetupListbox::GetInstance(GetDlgItem(hwnd, pmis->CtlID));
if (NULL != instance)
{
return instance->MeasureItem(pmis->itemID, &pmis->itemWidth, &pmis->itemHeight);
}
break;
}
return FALSE;
}
static BOOL SetupPage_OnDrawItem(HWND hwnd, DRAWITEMSTRUCT *pdis)
{
SetupListbox *instance;
switch(pdis->CtlID)
{
case IDC_SERVICELIST:
instance = SetupListbox::GetInstance(pdis->hwndItem);
if (NULL != instance)
{
return instance->DrawItem(pdis->hDC, &pdis->rcItem, pdis->itemID, pdis->itemState, pdis->itemAction);
}
break;
}
return FALSE;
}
static INT_PTR SetupPage_OnCharToItem(HWND hwnd, INT vKey, INT caretPos, HWND hList)
{
if (IDC_SERVICELIST == GetDlgCtrlID(hList))
{
SetupListbox *instance = SetupListbox::GetInstance(hList);
if (NULL != instance)
return instance->CharToItem(vKey, caretPos);
}
return -1;
}
static INT_PTR SetupPage_OnKeyToItem(HWND hwnd, INT vKey, INT caretPos, HWND hList)
{
if (IDC_SERVICELIST == GetDlgCtrlID(hList))
{
SetupListbox *instance = SetupListbox::GetInstance(hList);
if (NULL != instance)
return instance->KeyToItem(vKey, caretPos);
}
return -1;
}
static void SetupPage_OnUpdateList(HWND hwnd, INT groupId)
{
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
if (NULL != hList)
{
SetupListbox *listbox = SetupListbox::GetInstance(hList);
if (NULL != listbox)
{
listbox->UpdateCount();
}
}
}
static INT_PTR WINAPI SetupPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return SetupPage_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: SetupPage_OnDestroy(hwnd); break;
case WM_COMMAND: SetupPage_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
case WM_MEASUREITEM: return SetupPage_OnMeasureItem(hwnd, (MEASUREITEMSTRUCT*)lParam);
case WM_DRAWITEM: return SetupPage_OnDrawItem(hwnd, (DRAWITEMSTRUCT*)lParam);
case WM_CHARTOITEM: return SetupPage_OnCharToItem(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
case WM_VKEYTOITEM: return SetupPage_OnKeyToItem(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
case SPM_UPDATELIST: SetupPage_OnUpdateList(hwnd, (INT)wParam); return TRUE;
}
return 0;
}

View file

@ -0,0 +1,567 @@
#include "./main.h"
#include "../api__ml_online.h"
#include "./setupRecord.h"
#include "./setupDetails.h"
#include "./setupLog.h"
#include "../resource.h"
#include "./serviceHelper.h"
#include "./serviceHost.h"
#include <ifc_omservice.h>
#include <ifc_omwebstorage.h>
#include <ifc_omserviceenum.h>
#include <ifc_omservicecopier.h>
#include <wininet.h>
#include <strsafe.h>
#define RECORD_MARGINCX 6
#define RECORD_MARGINCY 2
#define CHECKBOX_MARGIN_RIGHT 2
#define TEXT_OFFSET_LEFT 3
#define TEXT_OFFSET_BOTTOM RECORD_MARGINCY
#define TEXT_ALIGN (TA_LEFT | TA_BOTTOM)
SetupRecord::SetupRecord(ifc_omservice *serviceToUse)
: ref(1), service(serviceToUse), flags(0), async(NULL)
{
if (NULL != service)
{
if (S_OK == ServiceHelper_IsSubscribed(service))
flags |= recordSelected;
service->AddRef();
}
InitializeCriticalSection(&lock);
}
SetupRecord::~SetupRecord()
{
EnterCriticalSection(&lock);
if (NULL != async)
{
ifc_omstorage *storage = NULL;
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
if (SUCCEEDED(hr) && storage != NULL)
{
storage->RequestAbort(async, TRUE);
}
async->Release();
async = NULL;
}
if (NULL != service)
service->Release();
LeaveCriticalSection(&lock);
DeleteCriticalSection(&lock);
}
SetupRecord *SetupRecord::CreateInstance(ifc_omservice *serviceToUse)
{
if (NULL == serviceToUse) return NULL;
return new SetupRecord(serviceToUse);
}
ULONG SetupRecord::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG SetupRecord::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT SetupRecord::GetServiceName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == service) return E_UNEXPECTED;
return service->GetName(pszBuffer, cchBufferMax);
}
HRESULT SetupRecord::GetDisplayName(LPWSTR pszBuffer, UINT cchBufferMax)
{
HRESULT hr = GetServiceName(pszBuffer, cchBufferMax);
if (SUCCEEDED(hr) && L'\0' == *pszBuffer)
{
WASABI_API_LNGSTRINGW_BUF(IDS_DEFAULT_SERVICENAME, pszBuffer, cchBufferMax);
DownloadDetails();
}
return hr;
}
HRESULT SetupRecord::DownloadDetails()
{
HRESULT hr;
EnterCriticalSection(&lock);
if (NULL == async && 0 == (recordDownloaded & flags))
{
WCHAR szUrl[INTERNET_MAX_URL_LENGTH] = {0};
hr = ServiceHelper_GetDetailsUrl(szUrl, ARRAYSIZE(szUrl), service, FALSE);
if (SUCCEEDED(hr))
{
ifc_omstorage *storage = NULL;
hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
if (SUCCEEDED(hr) && storage != NULL)
{
ServiceHost *serviceHost = NULL;
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
serviceHost = NULL;
hr = storage->BeginLoad(szUrl, serviceHost, SetupRecord_ServiceDownloadedCallback, this, &async);
storage->Release();
if (NULL != serviceHost)
serviceHost->Release();
}
}
}
else
{
hr = S_FALSE;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT SetupRecord::Save(SetupLog *log)
{
if (NULL == service) return E_POINTER;
HRESULT hr = ServiceHelper_Subscribe(service, IsSelected(), SHF_SAVE);
if (S_OK == hr)
{
if (NULL != log)
{
INT operation = (IsSelected()) ? SetupLog::opServiceAdded : SetupLog::opServiceRemoved;
log->LogService(service, operation);
}
}
return hr;
}
BOOL SetupRecord::IsModified()
{
if (NULL == service)
return FALSE;
if (S_OK == ServiceHelper_IsSubscribed(service) != (FALSE != IsSelected()))
return TRUE;
if (S_OK == ServiceHelper_IsModified(service))
return TRUE;
return FALSE;
}
BOOL SetupRecord::IsSelected()
{
return (0 != (recordSelected & flags));
}
void SetupRecord::SetSelected(BOOL fSelected)
{
if ((FALSE == fSelected) == !IsSelected())
return;
if (FALSE == fSelected)
flags &= ~recordSelected;
else
flags |= recordSelected;
}
BOOL SetupRecord::AdjustCheckboxRect(SetupListbox *instance, RECT *prcItem)
{
SIZE checkSize;
if (!instance->GetCheckboxMetrics(NULL, IsSelected(), 0, &checkSize))
return FALSE;
prcItem->left += RECORD_MARGINCX;
prcItem->right = prcItem->left + checkSize.cx;
if (checkSize.cy > (prcItem->bottom - prcItem->top))
checkSize.cy = (prcItem->bottom - prcItem->top);
prcItem->top += ((prcItem->bottom - prcItem->top) - checkSize.cy) / 2;
prcItem->bottom = prcItem->top + checkSize.cy;
return TRUE;
}
BOOL SetupRecord::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
{
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return FALSE;
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
SIZE checkSize;
instance->GetCheckboxMetrics(hdc, IsSelected(), 0, &checkSize);
if (NULL != cy)
{
*cy = 0;
TEXTMETRIC tm = {0};
if (GetTextMetrics(hdc, &tm))
{
*cy = tm.tmHeight + tm.tmExternalLeading;
if (checkSize.cy > (INT)*cy) *cy = checkSize.cy;
*cy += RECORD_MARGINCY*2;
}
}
if (NULL != cx)
{
*cx = checkSize.cx;
WCHAR szBuffer[128] = {0};
if (SUCCEEDED(GetDisplayName(szBuffer, ARRAYSIZE(szBuffer))))
{
INT cchBuffer = lstrlenW(szBuffer);
SIZE textSize;
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
{
*cx += textSize.cx;
if (0 != checkSize.cx)
*cx += CHECKBOX_MARGIN_RIGHT + RECORD_MARGINCX;
}
}
if (0 != *cx) *cx += RECORD_MARGINCX*2;
}
SelectObject(hdc, originalFont);
ReleaseDC(instance->GetHwnd(), hdc);
return TRUE;
}
void SetupRecord::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
{
COLORREF rgbBk, rgbText;
if (0 != (ODS_DISABLED & state))
{
rgbBk = GetBkColor(hdc);
rgbText = GetSysColor(COLOR_GRAYTEXT);
}
else if (0 != (ODS_SELECTED & state))
{
if (0 == (ODS_INACTIVE & state))
{
rgbBk = GetSysColor(COLOR_HIGHLIGHT);
rgbText = GetSysColor(COLOR_HIGHLIGHTTEXT);
}
else
{
rgbBk = GetSysColor(COLOR_3DFACE);
rgbText = GetTextColor(hdc);
}
}
else
{
rgbBk = GetBkColor(hdc);
rgbText = GetTextColor(hdc);
}
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
}
BOOL SetupRecord::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
{
LONG paintLeft = prc->left + RECORD_MARGINCX;
RECT partRect;
UINT checkState = state & ~ODS_SELECTED;
if (0 == (checkboxPressed & flags))
{
if (0 != (checkboxHighlighted & flags))
checkState |= ODS_HOTLIGHT;
}
else
{
checkState |= ((0 != (checkboxHighlighted & flags)) ? ODS_SELECTED : ODS_HOTLIGHT);
}
HRGN backRgn, rgn;
backRgn = CreateRectRgnIndirect(prc);
rgn = CreateRectRgn(0,0,0,0);
SetRectEmpty(&partRect);
instance->GetCheckboxMetrics(hdc, IsSelected(), checkState, (((SIZE*)&partRect) + 1));
INT space = (prc->bottom - prc->top) - (partRect.bottom- partRect.top);
INT offsetY = space / 2 + space%2;
if (offsetY < 0) offsetY = 0;
OffsetRect(&partRect, paintLeft, prc->top + offsetY);
if (instance->DrawCheckbox(hdc, IsSelected(), checkState, &partRect, prc))
{
paintLeft = partRect.right + CHECKBOX_MARGIN_RIGHT;
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
COLORREF rgbBk, rgbText;
GetColors(hdc, state, &rgbBk, &rgbText);
COLORREF origBk = SetBkColor(hdc, rgbBk);
COLORREF origText = SetTextColor(hdc, rgbText);
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
WCHAR szBuffer[128] = {0};
INT cchBuffer = 0;
if (SUCCEEDED(GetDisplayName(szBuffer, ARRAYSIZE(szBuffer))))
cchBuffer = lstrlenW(szBuffer);
SetRect(&partRect, paintLeft, prc->top, prc->right, prc->bottom);
if (ExtTextOut(hdc, partRect.left + TEXT_OFFSET_LEFT, partRect.bottom - TEXT_OFFSET_BOTTOM,
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
{
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
}
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
DrawFocusRect(hdc, &partRect);
if (NULL != backRgn)
{
PaintRgn(hdc, backRgn);
DeleteObject(backRgn);
}
if (NULL != rgn)
DeleteObject(rgn);
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
if (origBk != rgbBk) SetBkColor(hdc, origBk);
if (origText != rgbText) SetTextColor(hdc, origText);
return TRUE;
}
INT_PTR SetupRecord::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
{
switch(vKey)
{
case VK_SPACE:
InvertCheckbox(instance, prcItem);
return -2;
}
return -1;
}
BOOL SetupRecord::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
RECT checkboxRect;
BOOL fInvalidate = FALSE;
CopyRect(&checkboxRect, prcItem);
AdjustCheckboxRect(instance, &checkboxRect);
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
{
if (0 == (checkboxHighlighted & flags))
{
flags |= checkboxHighlighted;
fInvalidate = TRUE;
}
}
else
{
if (0 != (checkboxHighlighted & flags))
{
flags &= ~checkboxHighlighted;
fInvalidate = TRUE;
}
}
if (FALSE != fInvalidate)
instance->InvalidateRect(&checkboxRect, FALSE);
return FALSE;
}
BOOL SetupRecord::MouseLeave(SetupListbox *instance, const RECT *prcItem)
{
if (0 != (checkboxHighlighted & flags))
{
flags &= ~checkboxHighlighted;
RECT checkboxRect;
CopyRect(&checkboxRect, prcItem);
AdjustCheckboxRect(instance, &checkboxRect);
instance->InvalidateRect(&checkboxRect, FALSE);
}
return FALSE;
}
BOOL SetupRecord::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
RECT checkboxRect;
BOOL handled = FALSE;
CopyRect(&checkboxRect, prcItem);
AdjustCheckboxRect(instance, &checkboxRect);
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
prcItem->left <= pt.x && pt.x < (checkboxRect.right + CHECKBOX_MARGIN_RIGHT))
{
handled = TRUE;
if (checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
{
flags |= (checkboxHighlighted | checkboxPressed);
instance->SetCapture(this);
instance->InvalidateRect(&checkboxRect, FALSE);
}
}
return handled;
}
BOOL SetupRecord::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
RECT checkboxRect;
BOOL handled = FALSE;
CopyRect(&checkboxRect, prcItem);
AdjustCheckboxRect(instance, &checkboxRect);
if (0 != (checkboxPressed & flags))
{
flags &= ~checkboxPressed;
if (this == instance->GetCapture())
instance->ReleaseCapture();
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
{
SetSelected(!IsSelected());
handled = TRUE;
}
instance->InvalidateRect(&checkboxRect, FALSE);
}
return handled;
}
BOOL SetupRecord::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
InvertCheckbox(instance, prcItem);
return TRUE;
}
BOOL SetupRecord::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
BOOL SetupRecord::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
{
return FALSE;
}
void SetupRecord::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
{
}
void SetupRecord::InvertCheckbox(SetupListbox *instance, const RECT *prcItem)
{
SetSelected(!IsSelected());
if (NULL != instance && NULL != prcItem)
{
RECT checkboxRect;
CopyRect(&checkboxRect, prcItem);
AdjustCheckboxRect(instance, &checkboxRect);
instance->InvalidateRect(&checkboxRect, FALSE);
}
}
HWND SetupRecord::CreateDetailsView(HWND hParent)
{
DownloadDetails();
WCHAR szName[64] = {0};
if (FALSE == GetUniqueName(szName, ARRAYSIZE(szName)))
szName[0] = L'\0';
return SetupDetails_CreateServiceView(hParent, szName, service);
}
BOOL SetupRecord::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer ||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"record_svc_%u", service->GetId())))
{
return FALSE;
}
return TRUE;
}
void SetupRecord::OnDownloadCompleted()
{
ifc_omstorage *storage = NULL;
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
if (SUCCEEDED(hr) && service != NULL)
{
ifc_omserviceenum *serviceEnum = NULL;
hr = storage->EndLoad(async, &serviceEnum);
if (SUCCEEDED(hr) && serviceEnum != NULL)
{
EnterCriticalSection(&lock);
ifc_omservice *result = NULL;
while(S_OK == serviceEnum->Next(1, &result, NULL))
{
if (result)
{
if (result->GetId() == service->GetId())
{
ifc_omservicecopier *copier;
if (SUCCEEDED(result->QueryInterface(IFC_OmServiceCopier, (void**)&copier)))
{
copier->CopyTo(service, NULL);
copier->Release();
}
result->Release();
flags |= recordDownloaded;
break;
}
else
{
result->Release();
}
}
result = NULL;
}
LeaveCriticalSection(&lock);
serviceEnum->Release();
}
storage->Release();
}
EnterCriticalSection(&lock);
async->Release();
async = NULL;
LeaveCriticalSection(&lock);
}
void CALLBACK SetupRecord_ServiceDownloadedCallback(ifc_omstorageasync *result)
{
if (NULL == result) return;
SetupRecord *record = NULL;
if (SUCCEEDED(result->GetData((void**)&record)) && NULL != record)
{
record->OnDownloadCompleted();
}
}

View file

@ -0,0 +1,84 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./setupListbox.h"
class ifc_omservice;
class ifc_omstorageasync;
class SetupLog;
class SetupRecord : public SetupListboxItem
{
protected:
typedef enum
{
recordSelected = 0x0001,
recordDownloaded = 0x0002,
checkboxHighlighted = 0x0100,
checkboxPressed = 0x0200,
} RecordFlags;
protected:
SetupRecord(ifc_omservice *serviceToUse);
~SetupRecord();
public:
static SetupRecord *CreateInstance(ifc_omservice *serviceToUse);
public:
ULONG AddRef();
ULONG Release();
ifc_omservice *GetService() { return service; }
BOOL IsModified();
BOOL IsSelected();
void SetSelected(BOOL fSelected);
HRESULT GetServiceName(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetDisplayName(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT Save(SetupLog *log);
HRESULT DownloadDetails();
/* SetupListboxItem */
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
BOOL IsDisabled() { return FALSE; }
void Command(SetupListbox *instance, INT commandId, INT eventId) {}
HWND CreateDetailsView(HWND hParent);
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
protected:
BOOL AdjustCheckboxRect(SetupListbox *instance, RECT *prcItem);
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
void InvertCheckbox(SetupListbox *instance, const RECT *prcItem);
void OnDownloadCompleted();
private:
friend static void CALLBACK SetupRecord_ServiceDownloadedCallback(ifc_omstorageasync *result);
protected:
ULONG ref;
ifc_omservice *service;
ifc_omstorageasync *async;
CRITICAL_SECTION lock;
UINT flags;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER

View file

@ -0,0 +1,797 @@
#include "../common.h"
#include "./setupServicePanel.h"
#include "./setupDetails.h"
#include "./setupPage.h"
#include "../resource.h"
#include "../api__ml_online.h"
#include <ifc_omservice.h>
#include <ifc_omservicedetails.h>
#include <ifc_omcachemanager.h>
#include <ifc_omcachegroup.h>
#include <ifc_omcacherecord.h>
#include <ifc_imageloader.h>
#include <ifc_omgraphics.h>
#include <ifc_omserviceeventmngr.h>
#include <ifc_omserviceeditor.h>
#include <shlwapi.h>
#include <strsafe.h>
#define GetPanel(__hwnd) ((ServicePanel*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
#define GET_IDETAILS(__service, __details)\
(NULL != (service) && SUCCEEDED((service)->QueryInterface(IFC_OmServiceDetails, (void**)&(__details))))
ServicePanel::ServicePanel(LPCWSTR pszName, ifc_omservice *service)
: ref(1), name(NULL), service(NULL), hwnd(NULL), fontTitle(NULL), fontMeta(NULL), thumbnailCache(NULL)
{
name = Plugin_CopyString(pszName);
this->service = service;
if (NULL != service)
service->AddRef();
}
ServicePanel::~ServicePanel()
{
Plugin_FreeString(name);
if (NULL != service)
service->Release();
if (NULL != fontTitle)
DeleteObject(fontTitle);
if (NULL != fontMeta)
DeleteObject(fontMeta);
if (NULL != thumbnailCache)
thumbnailCache->Release();
}
HWND ServicePanel::CreateInstance(HWND hParent, LPCWSTR pszName, ifc_omservice *service, ServicePanel **instance)
{
ServicePanel *panel = new ServicePanel(pszName, service);
if (NULL == panel)
{
if (NULL != instance) *instance = NULL;
return NULL;
}
HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_SERVICEDETAILS, hParent, ServicePanel_DialogProc, (LPARAM)panel);
if (NULL != instance)
{
if (NULL != hwnd)
{
*instance = panel;
panel->AddRef();
}
else
*instance = NULL;
}
panel->Release();
return hwnd;
}
size_t ServicePanel::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t ServicePanel::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int ServicePanel::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_OmServiceEvent))
*object = static_cast<ifc_omserviceevent*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
static void CALLBACK ThreadCallback_ServiceChange(Dispatchable *instance, ULONG_PTR param1, ULONG_PTR param2)
{
ifc_omserviceevent *panel = (ifc_omserviceevent*)instance;
ifc_omservice *service = (ifc_omservice*)param1;
if (NULL != service)
{
if (NULL != panel)
panel->ServiceChange(service, (UINT)param2);
service->Release();
}
}
void ServicePanel::ServiceChange(ifc_omservice *service, unsigned int modifiedFlags)
{
DWORD currentTID = GetCurrentThreadId();
DWORD windowTID = GetWindowThreadProcessId(hwnd, NULL);
if (NULL != windowTID && currentTID != windowTID)
{
if(NULL != OMUTILITY)
{
service->AddRef();
if (FAILED(OMUTILITY->PostMainThreadCallback2(ThreadCallback_ServiceChange, (ifc_omserviceevent*)this, (ULONG_PTR)service, (ULONG_PTR)modifiedFlags)))
service->Release();
}
return;
}
if ( 0 != (ifc_omserviceeditor::modifiedName & modifiedFlags))
{
UpdateName();
HWND hPage = GetParent(hwnd);
if (NULL != hPage)
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)service->GetId(), NULL);
}
if ( 0 != (ifc_omserviceeditor::modifiedDescription & modifiedFlags))
UpdateDescription();
if ( 0 != (ifc_omserviceeditor::modifiedThumbnail& modifiedFlags))
UpdateThumbnail();
if ( 0 != ((ifc_omserviceeditor::modifiedAuthorFirst |
ifc_omserviceeditor::modifiedAuthorLast |
ifc_omserviceeditor::modifiedUpdated |
ifc_omserviceeditor::modifiedPublished) & modifiedFlags))
{
UpdateMeta();
}
}
HRESULT ServicePanel::LoadLocalThumbnail(LPCWSTR pszPath)
{
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
if (NULL == hThumbnail) return E_UNEXPECTED;
SendMessage(hThumbnail, WM_SETREDRAW, FALSE, 0L);
HBITMAP hBitmap = NULL;
BITMAPINFOHEADER header;
void *pixelData;
ifc_omimageloader *imageLoader;
if (SUCCEEDED(OMUTILITY->QueryImageLoader(NULL, pszPath, FALSE, &imageLoader)))
{
imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData);
imageLoader->Release();
}
if (NULL == hBitmap &&
SUCCEEDED(OMUTILITY->QueryImageLoader(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_SERVICE64X64_IMAGE), FALSE, &imageLoader)))
{
imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData);
imageLoader->Release();
}
HBITMAP hTest = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
if (NULL != hTest)
DeleteObject(hTest);
if (NULL != hBitmap)
{
hTest = (HBITMAP)SendMessage(hThumbnail, STM_GETIMAGE, IMAGE_BITMAP, 0L);
if (hTest != hBitmap)
{ // this is XP and up image copy was created and alpha channel will be handled properly
DeleteObject(hBitmap);
}
else
{ // fix alpha channel
if (32 == header.biBitCount)
{
HDC hdcFixed = CreateCompatibleDC(NULL);
if (NULL != hdcFixed)
{
BITMAPINFOHEADER headerFixed;
CopyMemory(&headerFixed, &header, sizeof(BITMAPINFOHEADER));
BYTE *pixelsFixed;
INT cx = header.biWidth;
INT cy = abs(header.biHeight);
HBITMAP bitmapFixed = CreateDIBSection(NULL, (LPBITMAPINFO)&headerFixed, DIB_RGB_COLORS, (void**)&pixelsFixed, NULL, 0);
if (NULL != bitmapFixed)
{
HBITMAP bitmapOrig = (HBITMAP)SelectObject(hdcFixed, bitmapFixed);
HBRUSH hb = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdcFixed, (LPARAM)hwnd);
if (NULL == hb)
hb = GetSysColorBrush(COLOR_3DFACE);
RECT rect;
SetRect(&rect, 0, 0, cx, cy);
FillRect(hdcFixed, &rect, hb);
ifc_omgraphics *graphics;
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
{
HDC hdcSrc = CreateCompatibleDC(NULL);
if (NULL != hdcSrc)
{
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xFF;
bf.AlphaFormat = AC_SRC_ALPHA;
RECT blendRect;
SetRect(&blendRect, 0, 0, cx, cy);
graphics->Premultiply((BYTE*)pixelData, cx, cy);
graphics->AlphaBlend(hdcFixed, &blendRect, hdcSrc, &blendRect, bf);
SelectObject(hdcSrc, bitmapSrcOrig);
DeleteDC(hdcSrc);
}
graphics->Release();
}
SelectObject(hdcFixed, bitmapOrig);
SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmapFixed);
DeleteObject(hBitmap);
}
DeleteDC(hdcFixed);
}
}
}
}
RECT clientRect;
if (GetClientRect(hThumbnail, &clientRect))
{
INT cx = clientRect.right - clientRect.left;
INT cy = clientRect.bottom - clientRect.top;
if (64 != cx || 64 != cy)
{
SetWindowPos(hThumbnail, NULL, 0, 0, 64, 64, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
}
SendMessage(hThumbnail, WM_SETREDRAW, TRUE, 0L);
if (0 != ShowWindow(hThumbnail, (NULL != hBitmap) ? SW_SHOWNA : SW_HIDE))
InvalidateRect(hThumbnail, NULL, TRUE);
return S_OK;
}
static void CALLBACK ThreadCallback_PathChanged(Dispatchable *instance, ULONG_PTR param1, ULONG_PTR param2)
{
ifc_omcachecallback *panel = (ifc_omcachecallback*)instance;
ifc_omcacherecord *record = (ifc_omcacherecord*)param1;
if (NULL != record)
{
if (NULL != panel)
panel->PathChanged(record);
record->Release();
}
}
void ServicePanel::PathChanged(ifc_omcacherecord *record)
{
if (NULL == hwnd || FALSE == IsWindow(hwnd))
return;
DWORD currentTID = GetCurrentThreadId();
DWORD windowTID = GetWindowThreadProcessId(hwnd, NULL);
if (NULL != windowTID && currentTID != windowTID)
{
if(NULL != OMUTILITY)
{
record->AddRef();
if (FAILED(OMUTILITY->PostMainThreadCallback2(ThreadCallback_PathChanged, (ifc_omcachecallback*)this, (ULONG_PTR)record, 0L)))
record->Release();
}
return;
}
WCHAR szPath[2048] = {0};
if (FAILED(record->GetPath(szPath, ARRAYSIZE(szPath))))
szPath[0] = L'\0';
LoadLocalThumbnail(szPath);
}
void ServicePanel::Attach(HWND hwnd)
{
this->hwnd = hwnd;
if (NULL != hwnd &&
FALSE != SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), this))
{
AddRef();
}
}
void ServicePanel::Detach()
{
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
if (NULL != thumbnailCache)
{
thumbnailCache->UnregisterCallback(this);
thumbnailCache->Release();
thumbnailCache = NULL;
}
if (NULL != service)
{
ifc_omserviceeventmngr *eventManager;
if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
{
eventManager->UnregisterHandler(this);
eventManager->Release();
}
}
Release();
}
HFONT ServicePanel::PickTitleFont(LPCWSTR pszTitle, INT cchTitle, INT maxWidth)
{
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
if (0 == GetObject(dialogFont, sizeof(LOGFONT), &lf))
return NULL;
HFONT titleFont = NULL;
if (cchTitle > 0)
{
LOGFONT lf;
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
lf.lfWidth = 0;
lf.lfWeight = FW_DONTCARE;
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT origFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
SIZE textSize;
INT heightLimit = (lf.lfHeight < 0) ? 1 : -1;
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
do
{
textSize.cx = 0;
if (NULL != titleFont) DeleteObject(titleFont);
titleFont = CreateFontIndirect(&lf);
if (NULL != titleFont)
{
SelectObject(hdc, titleFont);
GetTextExtentPoint32(hdc, pszTitle, cchTitle, &textSize);
}
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
} while(textSize.cx > maxWidth && lf.lfHeight != heightLimit);
if (0 == textSize.cx)
{
DeleteObject(titleFont);
titleFont = NULL;
}
SelectObject(hdc, origFont);
ReleaseDC(hwnd, hdc);
}
}
}
if (NULL == titleFont &&
0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
titleFont = CreateFontIndirect(&lf);
}
return titleFont;
}
LPCWSTR ServicePanel::FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax)
{
SYSTEMTIME st;
ZeroMemory(&st, sizeof(SYSTEMTIME));
LPCWSTR cursor;
cursor = pszDate;
INT index = 0;
for(;;)
{
INT iVal;
if (FALSE == StrToIntEx(cursor, STIF_DEFAULT, &iVal) || iVal < 1)
{
index = 0;
break;
}
if (0 == index)
{
if (iVal < 2000 || iVal > 2100)
break;
st.wYear = iVal;
index++;
}
else if (1 == index)
{
if (iVal < 1 || iVal > 12)
break;
st.wMonth = iVal;
index++;
}
else if (2 == index)
{
if (iVal < 1 || iVal > 31)
break;
st.wDay = iVal;
index++;
}
else
{
index = 0;
break;
}
while(L'\0' != *cursor && L'-' != *cursor) cursor++;
if (L'-' == *cursor) cursor++;
if (L'\0' == *cursor)
break;
}
if (3 == index &&
0 != GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszBuffer, cchBufferMax))
{
return pszBuffer;
}
return pszDate;
}
HRESULT ServicePanel::GetFullName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
*pszBuffer = L'\0';
if (NULL == service) return E_UNEXPECTED;
ifc_omservicedetails *details;
HRESULT hr = service->QueryInterface(IFC_OmServiceDetails, (void**)&details);
if (SUCCEEDED(hr))
{
hr = details->GetAuthorFirst(pszBuffer, cchBufferMax);
if (SUCCEEDED(hr))
{
UINT cchBuffer = lstrlen(pszBuffer);
LPWSTR cursor = pszBuffer + cchBuffer;
size_t remaining = cchBufferMax - cchBuffer;
if (cursor != pszBuffer)
{
hr = StringCchCopyEx(cursor, remaining, L" ", &cursor, &remaining, 0);
if (SUCCEEDED(hr))
{
hr = details->GetAuthorLast(cursor, (UINT)remaining);
if (FAILED(hr) || L'\0' == *cursor)
{
pszBuffer[cchBuffer] = L'\0';
}
}
}
}
}
return hr;
}
void ServicePanel::UpdateName()
{
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
if (NULL == hTitle) return;
WCHAR szBuffer[128] = {0};
if (NULL == service ||
FAILED(service->GetName(szBuffer, ARRAYSIZE(szBuffer))))
{
szBuffer[0] = L'\0';
}
INT cchBuffer = lstrlen(szBuffer);
RECT rc;
GetClientRect(hTitle, &rc);
HFONT font = PickTitleFont(szBuffer, cchBuffer, rc.right - rc.left);
if (NULL != font)
{
if (NULL != fontTitle)
DeleteObject(fontTitle);
fontTitle = font;
SendMessage(hTitle, WM_SETFONT, (WPARAM)fontTitle, 0L);
}
SetWindowText(hTitle, szBuffer);
InvalidateRect(hTitle, NULL, TRUE);
}
void ServicePanel::UpdateDescription()
{
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
if (NULL == hDescription) return;
WCHAR szBuffer[4096] = {0};
ifc_omservicedetails *details = 0;
if (GET_IDETAILS(service, details))
{
details->GetDescription(szBuffer, ARRAYSIZE(szBuffer));
details->Release();
}
SetupDetails_SetDescription(hDescription, szBuffer);
}
void ServicePanel::UpdateMeta()
{
HWND hMeta = GetDlgItem(hwnd, IDC_SERVICEMETA);
if (NULL == hMeta) return;
WCHAR szBuffer[512] = {0};
ifc_omservicedetails *svcdetails = 0;
if (GET_IDETAILS(service, svcdetails))
{
WCHAR szValue[256] = {0}, szPrefix[64] = {0};
HRESULT hr = S_OK;
LPWSTR cursor = szBuffer;
size_t remaining = ARRAYSIZE(szBuffer);
if (SUCCEEDED(GetFullName(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
{
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_BYAUTHOR, szPrefix, ARRAYSIZE(szPrefix));
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
L"%s%s", szPrefix, szValue);
}
if (SUCCEEDED(svcdetails->GetUpdated(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
{
if (cursor != szBuffer)
hr = StringCchCopyEx(cursor, remaining, L"\r\n", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
if (SUCCEEDED(hr))
{
WCHAR szDate[128] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_LASTUPDATED, szPrefix, ARRAYSIZE(szPrefix));
StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
L"%s%s", szPrefix, FormatDate(szValue, szDate, ARRAYSIZE(szDate)));
}
}
svcdetails->Release();
}
if (NULL == fontMeta)
{
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LOGFONT lf;
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
{
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma");
lf.lfWidth = 0;
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
lf.lfQuality = ANTIALIASED_QUALITY;
fontMeta = CreateFontIndirect(&lf);
}
if (NULL != fontMeta)
{
SendMessage(hMeta, WM_SETFONT, (WPARAM)fontMeta, 0L);
}
}
SetWindowText(hMeta, szBuffer);
if (0 != ShowWindow(hMeta, (L'\0' != szBuffer[0]) ? SW_SHOWNA : SW_HIDE))
InvalidateRect(hMeta, NULL, TRUE);
}
void ServicePanel::UpdateThumbnail()
{
if (NULL != thumbnailCache)
{
thumbnailCache->UnregisterCallback(this);
thumbnailCache->Release();
thumbnailCache = NULL;
}
LoadLocalThumbnail(NULL);
ifc_omservicedetails *details = 0;
if (GET_IDETAILS(service, details))
{
WCHAR szPath[2048] = {0};
if (SUCCEEDED(details->GetThumbnail(szPath, ARRAYSIZE(szPath))) && L'\0' != szPath[0])
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(OMUTILITY->GetCacheManager(&cacheManager)))
{
ifc_omcachegroup *cacheGroup;
if (SUCCEEDED(cacheManager->Find(L"thumbnails", TRUE, &cacheGroup, NULL)))
{
if (SUCCEEDED(cacheGroup->Find(szPath, TRUE, &thumbnailCache, FALSE)))
{
thumbnailCache->RegisterCallback(this);
if (SUCCEEDED(thumbnailCache->GetPath(szPath, ARRAYSIZE(szPath))))
LoadLocalThumbnail(szPath);
}
cacheGroup->Release();
}
cacheManager->Release();
}
}
details->Release();
}
}
INT_PTR ServicePanel::OnInitDialog(HWND hFocus, LPARAM lParam)
{
UpdateName();
UpdateDescription();
UpdateThumbnail();
UpdateMeta();
if (NULL != service)
{
ifc_omserviceeventmngr *eventManager;
if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
{
eventManager->RegisterHandler(this);
eventManager->Release();
}
}
return FALSE;
}
void ServicePanel::OnDestroy()
{
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
if (NULL != hThumbnail)
{
HBITMAP hBitmap = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, 0L);
if (NULL != hBitmap)
DeleteObject(hBitmap);
}
Detach();
}
INT_PTR ServicePanel::OnDialogColor(HDC hdc, HWND hControl)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
return 0;
}
INT_PTR ServicePanel::OnStaticColor(HDC hdc, HWND hControl)
{
INT_PTR result = 0;
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent && hParent != hwnd)
result = (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
INT controlId = GetDlgCtrlID(hControl);
switch(controlId)
{
case IDC_SERVICEMETA:
{
COLORREF rgbBk = GetBkColor(hdc);
COLORREF rgbFg = GetTextColor(hdc);
ifc_omgraphics *graphics;
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
{
graphics->BlendColor(rgbFg, rgbBk, 180, &rgbFg);
graphics->Release();
}
SetTextColor(hdc, rgbFg);
}
break;
}
return result;
}
INT_PTR ServicePanel::OnGetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return FALSE;
return SUCCEEDED(StringCchCopy(pszBuffer, cchBufferMax, (NULL != name) ? name : L""));
}
INT_PTR ServicePanel::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
case WM_DESTROY: OnDestroy(); break;
case WM_CTLCOLORDLG: return OnDialogColor((HDC)wParam, (HWND)lParam);
case WM_CTLCOLORSTATIC: return OnStaticColor((HDC)wParam, (HWND)lParam);
case NSDM_GETUNIQUENAME: MSGRESULT(hwnd, OnGetUniqueName((LPWSTR)lParam, (UINT)wParam));
}
return 0;
}
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ServicePanel *panel = GetPanel(hwnd);
if (NULL == panel)
{
if (WM_INITDIALOG == uMsg)
{
panel = (ServicePanel*)lParam;
if (NULL != panel)
panel->Attach(hwnd);
}
if (NULL == panel) return 0;
}
return panel->DialogProc(uMsg, wParam, lParam);
}
#define CBCLASS ServicePanel
START_MULTIPATCH;
START_PATCH(MPIID_SERVICEEVENT)
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, ADDREF, AddRef);
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, RELEASE, Release);
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, QUERYINTERFACE, QueryInterface);
M_VCB(MPIID_SERVICEEVENT, ifc_omserviceevent, API_SERVICECHANGE, ServiceChange);
NEXT_PATCH(MPIID_CACHECALLBACK)
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, ADDREF, AddRef);
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, RELEASE, Release);
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, QUERYINTERFACE, QueryInterface);
M_VCB(MPIID_CACHECALLBACK, ifc_omcachecallback, API_PATHCHANGED, PathChanged);
END_PATCH
END_MULTIPATCH;
#undef CBCLASS

View file

@ -0,0 +1,79 @@
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <bfc/multipatch.h>
#include <ifc_omserviceevent.h>
#include <ifc_omcachecallback.h>
class ifc_omservice;
#define MPIID_SERVICEEVENT 10
#define MPIID_CACHECALLBACK 20
class ServicePanel : public MultiPatch<MPIID_SERVICEEVENT, ifc_omserviceevent>,
public MultiPatch<MPIID_CACHECALLBACK, ifc_omcachecallback>
{
protected:
ServicePanel(LPCWSTR pszName, ifc_omservice *service);
~ServicePanel();
public:
static HWND CreateInstance(HWND hParent, LPCWSTR pszName, ifc_omservice *service, ServicePanel **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_omserviceevent */
void ServiceChange(ifc_omservice *service, unsigned int modifiedFlags);
/* ifc_omcachecallback */
void PathChanged(ifc_omcacherecord *record);
protected:
void Attach(HWND hwnd);
void Detach();
void UpdateName();
void UpdateDescription();
void UpdateMeta();
void UpdateThumbnail();
HFONT PickTitleFont(LPCWSTR pszTitle, INT cchTitle, INT maxWidth);
LPCWSTR FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax);
HRESULT GetFullName(LPWSTR pszBuffer, UINT cchBufferMax);
INT_PTR OnInitDialog(HWND hFocus, LPARAM lParam);
void OnDestroy();
INT_PTR OnDialogColor(HDC hdc, HWND hControl);
INT_PTR OnStaticColor(HDC hdc, HWND hControl);
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnGetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT LoadLocalThumbnail(LPCWSTR pszPath);
private:
friend static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
size_t ref;
HWND hwnd;
LPWSTR name;
ifc_omservice *service;
ifc_omcacherecord *thumbnailCache;
HFONT fontTitle;
HFONT fontMeta;
private:
RECVS_MULTIPATCH;
};
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER