Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@@ -0,0 +1,660 @@
#define OEMRESOURCE
#include "./addressEditbox.h"
#include "./common.h"
#include <richedit.h>
#include <strsafe.h>
#define NAEF_USERFLAGSMASK 0x00FFFFFF
#define NAEF_UNICODE 0x01000000
typedef struct __ADDRESSEDITBOX
{
WNDPROC originalProc;
UINT flags;
DWORD dblclkTime; LPWSTR rollbackText;
} ADDRESSEDITBOX;
#define ADDRESSEDITBOX_PROP L"NullsoftAddressEditbox"
#define GetEditbox(__hwnd) ((ADDRESSEDITBOX*)GetProp((__hwnd), ADDRESSEDITBOX_PROP))
static LRESULT CALLBACK AddressEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT CALLBACK AddressEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
static INT CALLBACK AddressEditbox_WordBreakProc2(LPWSTR pszText, INT iCurrent, INT cchLen, INT code);
BOOL AddressEditbox_AttachWindow(HWND hEditbox)
{
if (!IsWindow(hEditbox))
return FALSE;
ADDRESSEDITBOX *editbox = (ADDRESSEDITBOX*)GetProp(hEditbox, ADDRESSEDITBOX_PROP);
if (NULL != editbox) return TRUE;
editbox = (ADDRESSEDITBOX*)calloc(1, sizeof(ADDRESSEDITBOX));
if (NULL == editbox) return FALSE;
ZeroMemory(editbox, sizeof(ADDRESSEDITBOX));
if (IsWindowUnicode(hEditbox))
editbox->flags |= NAEF_UNICODE;
editbox->originalProc = (WNDPROC)(LONG_PTR)((0 != (NAEF_UNICODE & editbox->flags)) ?
SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)AddressEditbox_WindowProc) :
SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)AddressEditbox_WindowProc));
if (NULL == editbox->originalProc || !SetProp(hEditbox, ADDRESSEDITBOX_PROP, editbox))
{
if (NULL != editbox->originalProc)
{
if (0 != (NAEF_UNICODE & editbox->flags))
SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
else
SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
}
free(editbox);
return FALSE;
}
SendMessage(hEditbox, EM_SETWORDBREAKPROC, 0, (LPARAM)AddressEditbox_WordBreakProc);
if (FAILED(LoginBox_GetWindowText(hEditbox, &editbox->rollbackText, NULL)))
editbox->rollbackText = NULL;
return TRUE;
}
static void AddressEditbox_Detach(HWND hwnd)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
RemoveProp(hwnd, ADDRESSEDITBOX_PROP);
if (NULL == editbox)
return;
if (NULL != editbox->originalProc)
{
if (0 != (NAEF_UNICODE & editbox->flags))
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
else
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
}
free(editbox);
}
static LRESULT AddressEditbox_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
if (NULL == editbox || NULL == editbox->originalProc)
{
return (0 != (NAEF_UNICODE & editbox->flags)) ?
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
return (0 != (NAEF_UNICODE & editbox->flags)) ?
CallWindowProcW(editbox->originalProc, hwnd, uMsg, wParam, lParam) :
CallWindowProcA(editbox->originalProc, hwnd, uMsg, wParam, lParam);
}
static void AddressEditbox_SelectReplacementBlock(HWND hwnd, LPCWSTR pszText)
{
INT begin(-1), end(-1);
if (NULL != pszText)
{
LPCWSTR cursor = pszText;
while(L'\0' != *cursor)
{
if (-1 == begin)
{
if (REPLACE_MARKER_BEGIN == *cursor)
begin = (INT)(INT_PTR)(cursor - pszText);
}
else if (REPLACE_MARKER_END == *cursor)
{
end = (INT)(INT_PTR)(cursor - pszText) + 1;
break;
}
cursor = CharNext(cursor);
}
if (-1 == begin || -1 == end)
{
begin = (INT)(INT_PTR)(cursor - pszText);
end = begin + 1;
}
}
SendMessage(hwnd, EM_SETSEL, begin, end);
}
static void AddressEditbox_ResetText(HWND hwnd)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
if (NULL != editbox)
{
AddressEditbox_CallOrigWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)editbox->rollbackText);
AddressEditbox_SelectReplacementBlock(hwnd, editbox->rollbackText);
}
}
static BOOL AddressEditbox_IsDelimiterChar(WCHAR testChar)
{
WORD info;
if (FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &testChar, 1, &info))
return 0;
if (0 != ((C1_SPACE | C1_PUNCT | C1_CNTRL | C1_BLANK) & info) &&
REPLACE_MARKER_BEGIN != testChar && REPLACE_MARKER_END != testChar)
{
return TRUE;
}
return FALSE;
}
static INT AddressEditbox_FindLeft(LPCWSTR pszText, INT iCurrent, INT cchLen)
{
if (iCurrent <= 0)
return 0;
LPCWSTR pszCursor = &pszText[iCurrent];
BOOL charDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
for(;;)
{
pszCursor = CharPrev(pszText, pszCursor);
if (charDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
if (pszCursor == pszText)
break;
}
return 0;
}
static INT AddressEditbox_FindRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
{
if (iCurrent >= cchLen)
return cchLen;
LPCWSTR pszEnd = &pszText[cchLen];
LPCWSTR pszCursor = &pszText[iCurrent];
if (iCurrent > 0)
pszCursor = CharNext(pszCursor);
BOOL charDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
for(;;)
{
pszCursor = CharNext(pszCursor);
if (pszCursor >= pszEnd)
break;
if (charDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
return (INT)(INT_PTR)(pszCursor - pszText);
}
return cchLen;
}
static INT AddressEditbox_FindWordLeft(LPCWSTR pszText, INT iCurrent, INT cchLen, BOOL fRightCtrl)
{
if (iCurrent < 2)
return 0;
LPCWSTR pszCursor = &pszText[iCurrent];
if (FALSE == fRightCtrl)
pszCursor = CharPrev(pszText, pszCursor);
BOOL prevCharDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
for(;;)
{
pszCursor = CharPrev(pszText, pszCursor);
if (TRUE == AddressEditbox_IsDelimiterChar(*pszCursor))
{
if (FALSE == prevCharDelim)
return (INT)(INT_PTR)(CharNext(pszCursor) - pszText);
prevCharDelim = TRUE;
}
else
prevCharDelim = FALSE;
if (pszCursor == pszText)
break;
}
return 0;
}
static INT AddressEditbox_FindWordRight(LPCWSTR pszText, INT iCurrent, INT cchLen)
{
if ( iCurrent >= (cchLen - 1))
return cchLen;
LPCWSTR pszEnd = &pszText[cchLen];
LPCWSTR pszCursor = &pszText[iCurrent];
BOOL prevCharDelim = AddressEditbox_IsDelimiterChar(*pszCursor);
for(;;)
{
pszCursor = CharNext(pszCursor);
if (pszCursor >= pszEnd)
break;
if (prevCharDelim != AddressEditbox_IsDelimiterChar(*pszCursor))
{
prevCharDelim = TRUE;
return (INT)(INT_PTR)(pszCursor - pszText);
}
else
prevCharDelim = FALSE;
}
return cchLen;
}
static INT CALLBACK AddressEditbox_WordBreakProc(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
{
switch(code)
{
case WB_ISDELIMITER: return (iCurrent < 0) ? 0 : ((iCurrent > cchLen) ? (cchLen + 1) : AddressEditbox_IsDelimiterChar(pszText[iCurrent]));
case WB_LEFT: return AddressEditbox_FindLeft(pszText, iCurrent, cchLen);
case WB_RIGHT: return AddressEditbox_FindRight(pszText, iCurrent, cchLen);
case WB_MOVEWORDLEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
case WB_MOVEWORDRIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
}
return 0;
}
static INT CALLBACK AddressEditbox_WordBreakProcOverrideLeft(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
{
switch(code)
{
case WB_LEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, FALSE);
case WB_RIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
}
return AddressEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
}
static INT CALLBACK AddressEditbox_WordBreakProcOverrideRight(LPWSTR pszText, INT iCurrent, INT cchLen, INT code)
{
switch(code)
{
case WB_LEFT: return AddressEditbox_FindWordLeft(pszText, iCurrent, cchLen, TRUE);
case WB_RIGHT: return AddressEditbox_FindWordRight(pszText, iCurrent, cchLen);
}
return AddressEditbox_WordBreakProc(pszText, iCurrent, cchLen, code);
}
static void AddressEditbox_OnDestroy(HWND hwnd)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
WNDPROC originalProc = editbox->originalProc;
BOOL fUnicode = (0 != (NAEF_UNICODE & editbox->flags));
AddressEditbox_Detach(hwnd);
if (NULL != originalProc)
{
if (FALSE != fUnicode)
CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
else
CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
}
}
static LRESULT AddressEditbox_OnGetDlgCode(HWND hwnd, INT vKey, MSG* pMsg)
{
LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)pMsg);
switch(vKey)
{
case VK_ESCAPE:
return result |= DLGC_WANTALLKEYS;
}
result &= ~DLGC_HASSETSEL;
return result;
}
static void AddressEditbox_OnLButtonDown(HWND hwnd, UINT vKey, POINTS pts)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
if (NULL != editbox)
{
DWORD clickTime = GetTickCount();
if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + GetDoubleClickTime()))
{
SendMessage(hwnd, EM_SETSEL, 0, -1);
return;
}
}
AddressEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDOWN, (WPARAM)vKey, *((LPARAM*)&pts));
}
static void AddressEditbox_OnLButtonDblClk(HWND hwnd, UINT vKey, POINTS pts)
{
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
if (NULL == editbox) return;
DWORD clickTime = GetTickCount();
if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + 2*GetDoubleClickTime()))
{
INT r = (INT)SendMessage(hwnd, EM_CHARFROMPOS, 0, *(LPARAM*)&pts);
r = LOWORD(r);
SendMessage(hwnd, EM_SETSEL, (WPARAM)r, (LPARAM)r);
editbox->dblclkTime = 0;
}
else
{
editbox->dblclkTime = clickTime;
}
INT f, l;
SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
if (f != l) return;
AddressEditbox_CallOrigWindowProc(hwnd, WM_LBUTTONDBLCLK, (WPARAM)vKey, *((LPARAM*)&pts));
}
static void AddressEditbox_DeleteWord(HWND hwnd, UINT vKey, UINT state)
{
BOOL resetVisible = FALSE;
INT first, last;
SendMessage(hwnd, EM_GETSEL, (WPARAM)&first, (LPARAM)&last);
if (first == last)
{
UINT windowStyle = GetWindowStyle(hwnd);
if (0 != (WS_VISIBLE & windowStyle))
{
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
resetVisible = TRUE;
}
SendMessage(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
INT newFirst, newLast;
SendMessage(hwnd, EM_GETSEL, (WPARAM)&newFirst, (LPARAM)&newLast);
if (newFirst != first || newLast != last)
SendMessage(hwnd, EM_SETSEL, (WPARAM)first, (LPARAM)newLast);
}
SendMessage(hwnd, EM_REPLACESEL, TRUE, NULL);
if (FALSE != resetVisible)
{
UINT windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
InvalidateRect(hwnd, NULL, FALSE);
}
}
static void AddressEditbox_OnKeyDown(HWND hwnd, UINT vKey, UINT state)
{
EDITWORDBREAKPROC fnOrigBreak = NULL;
if(0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
{
switch(vKey)
{
case VK_LEFT:
case VK_RIGHT:
fnOrigBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
if (AddressEditbox_WordBreakProc == fnOrigBreak)
{
EDITWORDBREAKPROC fnOverride = (VK_LEFT == vKey) ?
AddressEditbox_WordBreakProcOverrideLeft : AddressEditbox_WordBreakProcOverrideRight;
SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOverride);
}
break;
case VK_DELETE:
AddressEditbox_DeleteWord(hwnd, VK_RIGHT, state);
return;
case VK_BACK:
AddressEditbox_DeleteWord(hwnd, VK_LEFT, state);
return;
}
}
AddressEditbox_CallOrigWindowProc(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
if (NULL != fnOrigBreak)
SendMessage(hwnd, EM_SETWORDBREAKPROC, 0, (LPARAM)fnOrigBreak);
}
static void AddressEditbox_OnChar(HWND hwnd, UINT vKey, UINT state)
{
if (0 != (0x8000 & GetAsyncKeyState(VK_CONTROL)))
{
UINT scanCode = (HIWORD(state) & 0x00FF);
vKey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
}
switch(vKey)
{
case VK_ESCAPE: AddressEditbox_ResetText(hwnd); return;
}
AddressEditbox_CallOrigWindowProc(hwnd, WM_CHAR, (WPARAM)vKey, (LPARAM)state);
}
static BOOL AddressEditbox_RemoveBadChars(LPCWSTR pszText, LPWSTR *bufferOut)
{
LPWSTR buffer = NULL;
if (NULL == pszText) return FALSE;
const WCHAR szBadChars[] = { L'\r', L'\n', L'\t', L'\0'};
BOOL fDetected = FALSE;
for (LPCWSTR p = pszText; L'\0' != *p && FALSE == fDetected; p++)
{
for (LPCWSTR b = szBadChars; L'\0' != *b; b++)
{
if (*p == *b)
{
fDetected = TRUE;
break;
}
}
}
if (FALSE == fDetected)
return FALSE;
if (NULL == bufferOut)
return TRUE;
INT cchText = lstrlen(pszText);
buffer = LoginBox_MallocString(cchText + 1);
if (NULL == buffer) return FALSE;
LPCWSTR s = pszText;
LPWSTR d = buffer;
LPCWSTR b;
for(;;)
{
for (b = szBadChars; L'\0' != *b && *s != *b; b++);
if(L'\0' != *b)
{
if (L'\t' == *b)
{
*d = L' ';
d++;
}
}
else
{
*d = *s;
d++;
}
if (L'\0' == *s)
break;
s++;
}
*bufferOut = buffer;
return TRUE;
}
static LRESULT AddressEditbox_OnSetText(HWND hwnd, LPCWSTR pszText)
{
LPWSTR buffer;
if (FALSE == AddressEditbox_RemoveBadChars(pszText, &buffer))
buffer = NULL;
else
pszText = buffer;
LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
ADDRESSEDITBOX *editbox = GetEditbox(hwnd);
if (NULL != editbox)
{
LoginBox_FreeString(editbox->rollbackText);
editbox->rollbackText = LoginBox_CopyString(pszText);
AddressEditbox_SelectReplacementBlock(hwnd, pszText);
}
if (NULL != buffer)
LoginBox_FreeString(buffer);
return result;
}
static LRESULT AddressEditbox_OnReplaceSel(HWND hwnd, BOOL fUndo, LPCWSTR pszText)
{
LPWSTR buffer;
if (FALSE == AddressEditbox_RemoveBadChars(pszText, &buffer))
buffer = NULL;
else
pszText = buffer;
LRESULT result = AddressEditbox_CallOrigWindowProc(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
if (NULL != buffer)
LoginBox_FreeString(buffer);
return result;
}
static void AddressEditbox_ReplaceText(HWND hwnd, LPCWSTR pszText, BOOL fUndo, BOOL fScrollCaret)
{
UINT windowStyle = GetWindowStyle(hwnd);
if (0 != (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
SendMessage(hwnd, EM_REPLACESEL, (WPARAM)fUndo, (LPARAM)pszText);
if (FALSE != fScrollCaret)
{
INT f, l;
SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
SendMessage(hwnd, EM_SETSEL, (WPARAM)f, (LPARAM)l);
}
if (0 != (WS_VISIBLE & windowStyle))
{
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
InvalidateRect(hwnd, NULL, FALSE);
}
}
static void AddressEditbox_OnPaste(HWND hwnd)
{
IDataObject *pObject;
HRESULT hr = OleGetClipboard(&pObject);
if (SUCCEEDED(hr))
{
FORMATETC fmt = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stgm;
hr = pObject->GetData(&fmt, &stgm);
if(S_OK == hr)
{
LPCWSTR pClipboard = (LPCWSTR)GlobalLock(stgm.hGlobal);
AddressEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
else
{
fmt.cfFormat = CF_TEXT;
hr = pObject->GetData(&fmt, &stgm);
if(S_OK == hr)
{
LPCSTR pClipboardAnsi = (LPCSTR)GlobalLock(stgm.hGlobal);
LPWSTR pClipboard;
if (FAILED(LoginBox_MultiByteToWideChar(CP_ACP, 0, pClipboardAnsi, -1, &pClipboard)))
pClipboard = NULL;
AddressEditbox_ReplaceText(hwnd, pClipboard, TRUE, TRUE);
LoginBox_FreeString(pClipboard);
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
}
pObject->Release();
}
}
static LRESULT AddressEditbox_OnFindWordBreak(HWND hwnd, INT code, INT start)
{
EDITWORDBREAKPROC fnBreak = (EDITWORDBREAKPROC)SendMessage(hwnd, EM_GETWORDBREAKPROC, 0, 0L);
if (NULL == fnBreak) return 0;
UINT cchText = GetWindowTextLength(hwnd);
if (0 == cchText) return 0;
LPWSTR pszText = LoginBox_MallocString(cchText + 1);
if (NULL == pszText) return 0;
LRESULT result = 0;
cchText = GetWindowText(hwnd, pszText, cchText + 1);
if (0 != cchText)
{
result = fnBreak(pszText, start, cchText, code);
}
LoginBox_FreeString(pszText);
return result;
}
static LRESULT CALLBACK AddressEditbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY: AddressEditbox_OnDestroy(hwnd); return 0;
case WM_GETDLGCODE: return AddressEditbox_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam);
case WM_LBUTTONDOWN: AddressEditbox_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_LBUTTONDBLCLK: AddressEditbox_OnLButtonDblClk(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_KEYDOWN: AddressEditbox_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam); return 0;
case WM_CHAR: AddressEditbox_OnChar(hwnd, (UINT)wParam, (UINT)lParam); return 0;
case WM_SETTEXT: return AddressEditbox_OnSetText(hwnd, (LPCWSTR)lParam);
case WM_PASTE: AddressEditbox_OnPaste(hwnd); return 1;
case EM_REPLACESEL: AddressEditbox_OnReplaceSel(hwnd, (BOOL)wParam, (LPCWSTR)lParam); return 0;
case EM_FINDWORDBREAK: return AddressEditbox_OnFindWordBreak(hwnd, (INT)wParam, (INT)lParam);
}
return AddressEditbox_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,15 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_ADDRESS_EDITBOX_HEADER
#define NULLSOFT_AUTH_LOGINBOX_ADDRESS_EDITBOX_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#define REPLACE_MARKER_BEGIN L'<'
#define REPLACE_MARKER_END L'>'
BOOL AddressEditbox_AttachWindow(HWND hEditbox);
#endif // NULLSOFT_AUTH_LOGINBOX_ADDRESS_EDITBOX_HEADER

View File

@@ -0,0 +1,514 @@
#include "./addressEncoder.h"
#include "./common.h"
#include <wininet.h>
#include <strsafe.h>
typedef struct __ENCODEBUFFER
{
LPWSTR buffer;
size_t bufferMax;
LPWSTR cursor;
size_t remaining;
} ENCODEBUFFER;
HRESULT AddressEncoder_ReAllocBuffer(ENCODEBUFFER *decoder, size_t cchBufferSize)
{
if (NULL == decoder)
return E_INVALIDARG;
if (cchBufferSize == decoder->bufferMax)
return S_FALSE;
if (cchBufferSize < decoder->bufferMax)
return E_FAIL;
LPWSTR test = LoginBox_ReAllocString(decoder->buffer, cchBufferSize);
if (NULL == test)
return E_OUTOFMEMORY;
decoder->cursor = test + (decoder->cursor - decoder->buffer);
decoder->remaining += (cchBufferSize - decoder->bufferMax);
decoder->buffer = test;
decoder->bufferMax = cchBufferSize;
return S_OK;
}
HRESULT AddressEncoder_AppendAnsiString(ENCODEBUFFER *decoder, LPCSTR pszString, size_t cchString)
{
if (NULL == decoder)
return E_INVALIDARG;
INT cchConverted;
while(0 ==(cchConverted = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pszString, (INT)cchString, decoder->cursor, (INT)decoder->remaining)))
{
DWORD errorCode = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == errorCode)
{
INT cchNeed = MultiByteToWideChar(CP_UTF8, 0, pszString, (INT)cchString, NULL, 0) - (INT)decoder->remaining;
if (cchNeed < 32) cchNeed = 32;
HRESULT hr = AddressEncoder_ReAllocBuffer(decoder, decoder->bufferMax + cchNeed);
if (FAILED(hr))
return hr;
}
else
{
return HRESULT_FROM_WIN32(errorCode);
}
}
if (0 != cchConverted)
{
decoder->cursor += cchConverted;
decoder->remaining -= cchConverted;
}
return S_OK;
}
HRESULT AddressEncoder_AppendString(ENCODEBUFFER *decoder, LPCWSTR pszString, size_t cchString)
{
if (NULL == decoder)
return E_INVALIDARG;
LPWSTR cursor;
size_t remaining;
HRESULT hr;
if (cchString >= decoder->remaining)
{
hr = AddressEncoder_ReAllocBuffer(decoder, decoder->bufferMax + (cchString - decoder->remaining) + 1);
if (FAILED(hr)) return hr;
}
hr = StringCchCopyNEx(decoder->cursor, decoder->remaining, pszString, cchString, &cursor, &remaining, 0);
if (SUCCEEDED(hr))
{
decoder->cursor = cursor;
decoder->remaining = remaining;
}
return hr;
}
HRESULT AddressEncoder_GetEscapeBlock(LPCWSTR pszEscape, LPCWSTR *ppszEnd, size_t *pcchEscapeLen, LPSTR pszBuffer, UINT *pcbBufferMax)
{
if (NULL == pszEscape || (NULL != pszBuffer && NULL == pcbBufferMax))
return E_INVALIDARG;
UINT cbBinary = 0;
WORD charInfo;
WCHAR szDigit[3] = {0};
HRESULT hr = S_OK;
LPCWSTR cursor = pszEscape;
while (L'%' == *cursor)
{
LPCWSTR testChar = CharNext(cursor);
if (L'\0' == *testChar ||
FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, testChar, 1, &charInfo) ||
0 == (C1_XDIGIT & charInfo))
{
break;
}
szDigit[0] = *testChar;
testChar = CharNext(testChar);
if (L'\0' == *testChar ||
FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, testChar, 1, &charInfo) ||
0 == (C1_XDIGIT & charInfo))
{
break;
}
szDigit[1] = *testChar;
CharUpperBuff(szDigit, 2);
BYTE binaryData = ((szDigit[0] - ((szDigit[0] <= L'9' ? L'0' : L'A' - 10))) << 4) & 0xf0;
binaryData += (szDigit[1] - ((szDigit[1] <= L'9' ? L'0' : L'A' - 10))) & 0x0f;
if (NULL != pszBuffer)
{
if (cbBinary < *pcbBufferMax)
pszBuffer[cbBinary] = binaryData;
else
hr = E_OUTOFMEMORY;
}
cbBinary++;
cursor = CharNext(testChar);
}
if (cursor == pszEscape)
hr = HRESULT_FROM_WIN32(ERROR_INVALID_BLOCK_LENGTH);
if (NULL != ppszEnd)
*ppszEnd = cursor;
if (NULL != pcchEscapeLen)
*pcchEscapeLen = (size_t)(cursor - pszEscape);
if (NULL != pcbBufferMax)
*pcbBufferMax = cbBinary;
return hr;
}
HRESULT AddressEncoder_DecodeString(LPCWSTR pszUrl, LPWSTR *ppResult)
{
if (NULL == pszUrl)
{
*ppResult = NULL;
return S_FALSE;
}
UINT cchUrl = 0;
UINT escapeSize = 0;
UINT escapeBlockSize,escapeBlockMaxSize = 0;
LPCWSTR escapeBlockEnd;
for (LPCWSTR cursor = pszUrl; L'\0' != *cursor;)
{
if (L'%' == *cursor && SUCCEEDED(AddressEncoder_GetEscapeBlock(cursor, &escapeBlockEnd, NULL, NULL, &escapeBlockSize)))
{
escapeSize += escapeBlockSize;
if (escapeBlockSize > escapeBlockMaxSize)
escapeBlockMaxSize = escapeBlockSize;
cursor = escapeBlockEnd;
}
else
{
cchUrl++;
cursor = CharNext(cursor);
}
}
if (0 == escapeSize)
{
*ppResult = LoginBox_CopyString(pszUrl);
if (NULL == *ppResult) return E_OUTOFMEMORY;
return S_FALSE;
}
HRESULT hr = S_OK;
ENCODEBUFFER decoder;
ZeroMemory(&decoder, sizeof(decoder));
LPSTR escapeBuffer = LoginBox_MallocAnsiString(escapeBlockMaxSize);
if (NULL == escapeBuffer)
{
hr = E_OUTOFMEMORY;
}
else
{
hr = AddressEncoder_ReAllocBuffer(&decoder, cchUrl + (escapeSize + 1)* sizeof(WCHAR));
if (SUCCEEDED(hr))
{
LPCWSTR cursor = pszUrl;
LPCWSTR copyBlock = cursor;
for (;;)
{
escapeBlockSize = escapeBlockMaxSize;
if (L'%' == *cursor && SUCCEEDED(AddressEncoder_GetEscapeBlock(cursor, &escapeBlockEnd, NULL, escapeBuffer, &escapeBlockSize)))
{
if (copyBlock != cursor)
{
hr = AddressEncoder_AppendString(&decoder, copyBlock, cursor - copyBlock);
if (FAILED(hr))
break;
copyBlock = cursor;
}
HRESULT convertResult = AddressEncoder_AppendAnsiString(&decoder, escapeBuffer, escapeBlockSize);
if (L'\0' == *cursor)
break;
cursor = escapeBlockEnd;
if (SUCCEEDED(convertResult))
{
copyBlock = cursor;
}
continue;
}
if (L'\0' == *cursor)
{
if (copyBlock != cursor)
hr = AddressEncoder_AppendString(&decoder, copyBlock, cursor - copyBlock);
break;
}
else
cursor = CharNext(cursor);
}
}
}
if (NULL != escapeBuffer)
LoginBox_FreeAnsiString(escapeBuffer);
if (FAILED(hr))
{
LoginBox_FreeString(decoder.buffer);
decoder.buffer = NULL;
}
else
{
*decoder.cursor = L'\0';
}
*ppResult = decoder.buffer;
return hr;
}
HRESULT AddressEncoder_GetWideBlock(LPCWSTR pszWide, LPCWSTR *pszEnd, LPWSTR pszBuffer, size_t *pcchBufferMax)
{
LPCWSTR cursor = pszWide;
if (NULL == pszWide)
return E_INVALIDARG;
if (NULL != pszBuffer && NULL == pcchBufferMax)
return E_INVALIDARG;
while (L'\0' == *cursor || *cursor > 0xFF)
{
if (L'\0' == *cursor)
break;
cursor = CharNext(cursor);
}
if (NULL != pszEnd)
*pszEnd = cursor;
HRESULT hr = S_OK;
size_t cchBuffer = 0;
if (cursor == pszWide)
{
hr = S_FALSE;
}
else
{
size_t bytesCount = WideCharToMultiByte(CP_UTF8, 0, pszWide, (INT)(INT_PTR)(cursor - pszWide), NULL, 0, NULL, NULL);
if (0 == bytesCount)
{
DWORD errorCode = GetLastError();
if (ERROR_SUCCESS != errorCode)
hr = HRESULT_FROM_WIN32(errorCode);
}
else
{
cchBuffer = 3 * bytesCount;
if (NULL != pszBuffer)
{
if (*pcchBufferMax >= cchBuffer)
{
LPWSTR p = pszBuffer;
BYTE *bytes = ((BYTE*)(pszBuffer + *pcchBufferMax)) - bytesCount;
WideCharToMultiByte(CP_UTF8, 0, pszWide, (INT)(INT_PTR)(cursor - pszWide), (LPSTR)bytes, (INT)bytesCount, NULL, NULL);
for (size_t i = 0; i < bytesCount; i++)
{
BYTE b = bytes[i];
*p++ = L'%';
BYTE c = (b >> 4) & 0x0F;
*p++ = (c < 10) ? (L'0' + c) : (L'A' + (c -10));
c = b & 0x0F;
*p++ = (c < 10) ? (L'0' + c) : (L'A' + (c -10));
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
}
if (NULL != pcchBufferMax)
{
*pcchBufferMax = cchBuffer;
}
return hr;
}
HRESULT AddressEncoder_EncodeWideChars(LPCWSTR pszAddress, size_t cchAddress, LPWSTR *ppResult)
{
if (NULL == ppResult)
return E_POINTER;
if (NULL == pszAddress)
{
*ppResult = NULL;
return S_FALSE;
}
LPCWSTR blockEnd;
size_t blockSize;
size_t cchResultMax = 0;
BOOL needEncode = FALSE;
for (LPCWSTR cursor = pszAddress; L'\0' != *cursor;)
{
if (*cursor > 0xFF && SUCCEEDED(AddressEncoder_GetWideBlock(cursor, &blockEnd, NULL, &blockSize)))
{
cursor = blockEnd;
cchResultMax += blockSize;
needEncode = TRUE;
}
else
{
cursor = CharNext(cursor);
cchResultMax++;
}
}
if (FALSE == needEncode)
{
*ppResult = NULL;
return S_FALSE;
}
HRESULT hr;
cchResultMax++;
LPWSTR result = LoginBox_MallocString(cchResultMax);
if (NULL == result)
hr = E_OUTOFMEMORY;
else
{
LPWSTR cursor = result;
size_t remaining = cchResultMax;
LPCWSTR address = pszAddress;
LPCWSTR addressBlock = address;
for (;;)
{
if (*address > 0xFF)
{
if (addressBlock != address)
{
hr = StringCchCopyNEx(cursor, remaining, addressBlock, (size_t)(address - addressBlock), &cursor, &remaining, 0);
if (FAILED(hr)) break;
}
blockSize = remaining;
hr = AddressEncoder_GetWideBlock(address, &address, cursor, &blockSize);
if (FAILED(hr)) break;
cursor += blockSize;
remaining -= blockSize;
addressBlock = address;
continue;
}
if (L'\0' == *address)
{
if (addressBlock != address)
{
hr = StringCchCopyNEx(cursor, remaining, addressBlock, (size_t)(address - addressBlock), &cursor, &remaining, 0);
}
break;
}
else
address = CharNext(address);
}
*cursor = L'\0';
}
if (FAILED(hr))
{
LoginBox_FreeString(result);
result = NULL;
}
*ppResult = result;
return hr;
}
HRESULT AddressEncoder_EncodeString(LPCWSTR pszAddress, LPWSTR pszBuffer, size_t *pcchBufferMax, UINT flags)
{
if (NULL == pszBuffer || NULL == pcchBufferMax)
return E_INVALIDARG;
if (NULL == pszAddress || L'\0' == *pszAddress)
{
*pszBuffer = L'\0';
*pcchBufferMax = 0;
return S_OK;
}
INT cchAddress = lstrlen(pszAddress);
LPCWSTR begin, end;
begin = pszAddress;
end = pszAddress + cchAddress;
WORD charType;
while (L'\0' != *begin &&
FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, begin, 1, &charType) && 0 != (C1_SPACE & charType))
{
begin = CharNext(begin);
}
while (begin != end &&
FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, begin, 1, &charType) && 0 != (C1_SPACE & charType))
{
end = CharPrev(begin, end);
}
if (end <= begin)
{
*pszBuffer = L'\0';
*pcchBufferMax = 0;
return S_OK;
}
LPWSTR encoded;
HRESULT hr = AddressEncoder_EncodeWideChars(begin, (end - begin), &encoded);
if (FAILED(hr)) return hr;
if (S_OK == hr)
{
begin = encoded;
end = begin + lstrlen(begin);
}
DWORD bufferLen = (DWORD)(*pcchBufferMax);
if (FALSE == InternetCanonicalizeUrl(begin, pszBuffer, &bufferLen, flags))
{
DWORD errorCode = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == errorCode)
{
*pcchBufferMax = bufferLen;
hr = ENC_E_INSUFFICIENT_BUFFER;
}
else
{
size_t cchNeeded = (end - begin);
if (cchNeeded < *pcchBufferMax)
{
hr = StringCchCopyN(pszBuffer, *pcchBufferMax, begin, cchNeeded);
if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
{
hr = ENC_E_INSUFFICIENT_BUFFER;
}
}
else
{
hr = ENC_E_INSUFFICIENT_BUFFER;
}
*pcchBufferMax = cchNeeded + 1;
}
}
else
hr = S_OK;
LoginBox_FreeString(encoded);
return hr;
}

View File

@@ -0,0 +1,15 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_ADDRESS_ENCODER_HEADER
#define NULLSOFT_AUTH_LOGINBOX_ADDRESS_ENCODER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#define ENC_E_INSUFFICIENT_BUFFER (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
HRESULT AddressEncoder_DecodeString(LPCWSTR pszAddress, LPWSTR *ppResult);
HRESULT AddressEncoder_EncodeString(LPCWSTR pszAddress, LPWSTR pszBuffer, size_t *pcchBufferMax, UINT flags);
#endif //NULLSOFT_AUTH_LOGINBOX_ADDRESS_ENCODER_HEADER

View File

@@ -0,0 +1,77 @@
#include "./animation.h"
#include "./common.h"
BOOL Animation_Initialize(ANIMATIONDATA *animation, UINT durationMs)
{
if (NULL == animation)
return FALSE;
if (FALSE == QueryPerformanceFrequency(&animation->frequency))
return FALSE;
QueryPerformanceCounter(&animation->completion);
animation->completion.QuadPart += animation->frequency.QuadPart*durationMs/1000LL;
return TRUE;
}
BOOL Animation_BeginStep(ANIMATIONDATA *animation)
{
if (NULL == animation || FALSE == QueryPerformanceCounter(&animation->stepBegin))
return FALSE;
return TRUE;
}
BOOL Animation_EndStep(ANIMATIONDATA *animation, size_t stepsRemaining)
{
if (NULL == animation || FALSE == QueryPerformanceCounter(&animation->stepEnd))
return FALSE;
if (0 == stepsRemaining || animation->stepEnd.QuadPart >= animation->completion.QuadPart)
return TRUE;
LARGE_INTEGER sleep;
sleep.QuadPart = (animation->completion.QuadPart - animation->stepEnd.QuadPart) -
(stepsRemaining * (animation->stepEnd.QuadPart - animation->stepBegin.QuadPart));
if (stepsRemaining > 1)
sleep.QuadPart /= (stepsRemaining -1);
if (sleep.QuadPart <= 0)
return TRUE;
sleep.QuadPart += animation->stepEnd.QuadPart;
do
{
SleepEx(0, FALSE);
QueryPerformanceCounter(&animation->stepEnd);
} while(sleep.QuadPart > animation->stepEnd.QuadPart);
return TRUE;
}
BOOL Animation_SetWindowPos(HWND hwnd, INT x, INT y, INT cx, INT cy, UINT flags, HDC hdc, INT contextX, INT contextY)
{
if (NULL == hwnd ||
FALSE == SetWindowPos(hwnd, NULL, x, y, cx, cy,
flags | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOCOPYBITS))
{
return FALSE;
}
UINT windowStyle = GetWindowStyle(hwnd);
POINT origPoint;
SetViewportOrgEx(hdc, contextX, contextY, &origPoint);
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | WS_VISIBLE);
if (FALSE == LoginBox_PrintWindow(hwnd, hdc, 0))
SendMessage(hwnd, WM_PRINT, (WPARAM)hdc, (LPARAM)(PRF_CLIENT | PRF_ERASEBKGND | PRF_CHILDREN | PRF_NONCLIENT));
if (0 == (WS_VISIBLE & windowStyle))
SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
SetViewportOrgEx(hdc, origPoint.x, origPoint.y, NULL);
return TRUE;
}

View File

@@ -0,0 +1,23 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_ANIMATION_HEADER
#define NULLSOFT_AUTH_LOGINBOX_ANIMATION_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef struct __ANIMATIONDATA
{
LARGE_INTEGER frequency;
LARGE_INTEGER completion;
LARGE_INTEGER stepBegin;
LARGE_INTEGER stepEnd;
} ANIMATIONDATA;
BOOL Animation_Initialize(ANIMATIONDATA *animation, UINT durationMs);
BOOL Animation_BeginStep(ANIMATIONDATA *animation);
BOOL Animation_EndStep(ANIMATIONDATA *animation, size_t stepsRemaining);
BOOL Animation_SetWindowPos(HWND hwnd, INT x, INT y, INT cx, INT cy, UINT flags, HDC hdc, INT contextX, INT contextY);
#endif //NULLSOFT_AUTH_LOGINBOX_ANIMATION_HEADER

View File

@@ -0,0 +1,19 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_BROWSER_EVENT_HEADER
#define NULLSOFT_AUTH_LOGINBOX_BROWSER_EVENT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class __declspec(novtable) BrowserEvent : public IUnknown
{
public:
STDMETHOD_(void, Event_BrowserReady)(HWND hBrowser) = 0;
STDMETHOD_(void, Event_DocumentReady)(HWND hBrowser) = 0;
STDMETHOD_(void, Event_BrowserClosing)(HWND hBrowser) = 0;
STDMETHOD_(void, Event_InvokeApc)(HWND hBrowser, LPARAM param) = 0;
};
#endif // NULLSOFT_AUTH_LOGINBOX_BROWSER_EVENT_HEADER

View File

@@ -0,0 +1,198 @@
#include "./browserWindow.h"
#include "./browserEvent.h"
#include "./common.h"
#include "../../ombrowser/browserHost.h"
#define NBWF_USERFLAGSMASK 0x00FFFFFF
#define NBWF_UNICODE 0x01000000
typedef struct __BROWSERWND
{
WNDPROC originalProc;
UINT flags;
BrowserEvent *eventHandler;
} BROWSERWND;
#define BROWSERWND_PROP L"NullsoftLoginboxBrowserWindow"
#define GetBrowserWnd(__hwnd) ((BROWSERWND*)GetProp((__hwnd), BROWSERWND_PROP))
static UINT NBWM_QUEUEAPC = 0;
static LRESULT CALLBACK BrowserWindow_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL BrowserWindow_Attach(HWND hBrowser, BrowserEvent *eventHandler)
{
if (!IsWindow(hBrowser))
return FALSE;
if (0 == NBWM_QUEUEAPC)
NBWM_QUEUEAPC = RegisterWindowMessage(L"NullsoftBrowserExtMessage");
BROWSERWND *browserWnd = (BROWSERWND*)GetProp(hBrowser, BROWSERWND_PROP);
if (NULL != browserWnd) return TRUE;
browserWnd = (BROWSERWND*)calloc(1, sizeof(BROWSERWND));
if (NULL == browserWnd) return FALSE;
ZeroMemory(browserWnd, sizeof(BROWSERWND));
if (IsWindowUnicode(hBrowser))
browserWnd->flags |= NBWF_UNICODE;
browserWnd->originalProc = (WNDPROC)(LONG_PTR)((0 != (NBWF_UNICODE & browserWnd->flags)) ?
SetWindowLongPtrW(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)BrowserWindow_WindowProc) :
SetWindowLongPtrA(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)BrowserWindow_WindowProc));
if (NULL == browserWnd->originalProc || !SetProp(hBrowser, BROWSERWND_PROP, browserWnd))
{
if (NULL != browserWnd->originalProc)
{
if (0 != (NBWF_UNICODE & browserWnd->flags))
SetWindowLongPtrW(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)browserWnd->originalProc);
else
SetWindowLongPtrA(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)browserWnd->originalProc);
}
free(browserWnd);
return FALSE;
}
if (NULL != eventHandler)
{
browserWnd->eventHandler = eventHandler;
eventHandler->AddRef();
}
return TRUE;
}
BOOL BrowserWindow_Detach(HWND hBrowser)
{
if (NULL == hBrowser || FALSE == IsWindow(hBrowser))
return FALSE;
BROWSERWND *browserWnd = GetBrowserWnd(hBrowser);
RemoveProp(hBrowser, BROWSERWND_PROP);
if (NULL == browserWnd)
return FALSE;
if (NULL != browserWnd->originalProc)
{
if (0 != (NBWF_UNICODE & browserWnd->flags))
SetWindowLongPtrW(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)browserWnd->originalProc);
else
SetWindowLongPtrA(hBrowser, GWLP_WNDPROC, (LONGX86)(LONG_PTR)browserWnd->originalProc);
}
if (NULL != browserWnd->eventHandler)
browserWnd->eventHandler->Release();
free(browserWnd);
return TRUE;
}
BOOL BrowserWindow_QueueApc(HWND hBrowser, LPARAM param)
{
if (0 == NBWM_QUEUEAPC ||
NULL == hBrowser || FALSE == IsWindow(hBrowser))
{
return FALSE;
}
return PostMessage(hBrowser, NBWM_QUEUEAPC, 0, (LPARAM)param);
}
static LRESULT BrowserWindow_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BROWSERWND *browserWnd = GetBrowserWnd(hwnd);
if (NULL == browserWnd || NULL == browserWnd->originalProc)
{
return (0 != (NBWF_UNICODE & browserWnd->flags)) ?
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
return (0 != (NBWF_UNICODE & browserWnd->flags)) ?
CallWindowProcW(browserWnd->originalProc, hwnd, uMsg, wParam, lParam) :
CallWindowProcA(browserWnd->originalProc, hwnd, uMsg, wParam, lParam);
}
static void BrowserWindow_OnDestroy(HWND hwnd)
{
BROWSERWND *browserWnd = GetBrowserWnd(hwnd);
WNDPROC originalProc = browserWnd->originalProc;
BOOL fUnicode = (0 != (NBWF_UNICODE & browserWnd->flags));
BrowserWindow_Detach(hwnd);
if (NULL != originalProc)
{
if (FALSE != fUnicode)
CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
else
CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
}
}
static void BrowserWindow_OnQueueApc(HWND hwnd, LPARAM param)
{
BROWSERWND *browserWnd = GetBrowserWnd(hwnd);
if (NULL != browserWnd && NULL != browserWnd->eventHandler)
browserWnd->eventHandler->Event_InvokeApc(hwnd, param);
}
static void BrowserWindow_OnBrowserNotify(HWND hwnd, NMHDR *pnmh)
{
BROWSERWND *browserWnd = GetBrowserWnd(hwnd);
if (NULL == browserWnd || NULL == browserWnd->eventHandler)
return;
switch(pnmh->code)
{
case NBHN_READY:
browserWnd->eventHandler->Event_BrowserReady(hwnd);
break;
case NBHN_DOCUMENTREADY:
browserWnd->eventHandler->Event_DocumentReady(hwnd);
break;
case NBHN_CLOSING:
browserWnd->eventHandler->Event_BrowserClosing(hwnd);
break;
}
}
static LRESULT BrowserWindow_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh)
{
LRESULT result = BrowserWindow_CallOrigWindowProc(hwnd, WM_NOTIFY, (WPARAM)controlId, (LPARAM)pnmh);
switch(controlId)
{
case 0x1000/*IDC_BROWSER*/:
BrowserWindow_OnBrowserNotify(hwnd, pnmh);
break;
}
return result;
}
static LRESULT CALLBACK BrowserWindow_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY: BrowserWindow_OnDestroy(hwnd); return 0;
case WM_NOTIFY: return BrowserWindow_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam);
}
if (NULL != NBWM_QUEUEAPC && NBWM_QUEUEAPC == uMsg)
{
BrowserWindow_OnQueueApc(hwnd, lParam);
return 0;
}
return BrowserWindow_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,16 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_BROWSER_WINDOW_HEADER
#define NULLSOFT_AUTH_LOGINBOX_BROWSER_WINDOW_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class BrowserEvent;
BOOL BrowserWindow_Attach(HWND hBrowser, BrowserEvent *eventHandler);
BOOL BrowserWindow_Detach(HWND hBrowser);
BOOL BrowserWindow_QueueApc(HWND hBrowser, LPARAM param);
#endif // NULLSOFT_AUTH_LOGINBOX_BROWSER_WINDOW_HEADER

View File

@@ -0,0 +1,82 @@
#include "./commandNodeParser.h"
#include "./loginCommand.h"
#include "./loginProvider.h"
#include "../../xml/obj_xml.h"
LoginCommandNodeParser::LoginCommandNodeParser()
: reader(NULL), provider(NULL)
{
}
LoginCommandNodeParser::~LoginCommandNodeParser()
{
End();
}
HRESULT LoginCommandNodeParser::Begin(obj_xml *pReader, LoginProvider *pProvider)
{
if (NULL != reader || NULL != provider)
return E_PENDING;
if (NULL == pReader || NULL == pProvider)
return E_INVALIDARG;
reader = pReader;
reader->AddRef();
provider = pProvider;
provider->AddRef();
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fcommand", this);
return S_OK;
}
HRESULT LoginCommandNodeParser::End()
{
if (NULL != reader)
{
reader->xmlreader_unregisterCallback(this);
reader->Release();
reader = NULL;
}
if (NULL != provider)
{
provider->Release();
provider = NULL;
}
return S_OK;
}
void LoginCommandNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementParser.Begin(reader, params);
}
void LoginCommandNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
LoginCommand *result;
if (SUCCEEDED(elementParser.End(reader, &result)))
{
if (NULL != provider)
provider->SetCommand(result);
result->Release();
}
}
void LoginCommandNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
}
#define CBCLASS LoginCommandNodeParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,41 @@
#ifndef NULLSOFT_AUTH_LOGIN_COMMAND_NODE_PARSER_HEADER
#define NULLSOFT_AUTH_LOGIN_COMMAND_NODE_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./commandParser.h"
class obj_xml;
class LoginCommand;
class LoginProvider;
class LoginCommandNodeParser : public ifc_xmlreadercallback
{
public:
LoginCommandNodeParser();
~LoginCommandNodeParser();
public:
HRESULT Begin(obj_xml *reader, LoginProvider *provider);
HRESULT End();
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
LoginCommandParser elementParser;
LoginProvider *provider;
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGIN_COMMAND_NODE_PARSER_HEADER

View File

@@ -0,0 +1,108 @@
#include "./commandParser.h"
#include "./loginCommand.h"
#include "./commandWinampAuth.h"
#include "./commandWebAuth.h"
#include "./common.h"
#include "../../xml/obj_xml.h"
LoginCommandParser::LoginCommandParser()
: object(NULL)
{
}
LoginCommandParser::~LoginCommandParser()
{
if (NULL != object)
object->Release();
}
HRESULT LoginCommandParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
{
if (NULL != object)
return E_PENDING;
if (NULL == reader || NULL == params)
return E_INVALIDARG;
GUID commandId;
LPCWSTR pszId = params->getItemValue(L"id");
if (NULL == pszId || RPC_S_OK != UuidFromString((RPC_WSTR)pszId, &commandId))
return E_INVALIDARG;
HRESULT hr;
if (IsEqualGUID(LCUID_WINAMPAUTH, commandId))
hr = LoginCommandWinampAuth::CreateInstance((LoginCommandWinampAuth**)&object);
else if (IsEqualGUID(LCUID_WEBAUTH, commandId))
hr = LoginCommandWebAuth::CreateInstance((LoginCommandWebAuth**)&object);
else
hr = E_INVALIDARG;
if (SUCCEEDED(hr))
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fcommand\f*", this);
return hr;
}
HRESULT LoginCommandParser::End(obj_xml *reader, LoginCommand **instance)
{
if (NULL == object)
return E_UNEXPECTED;
HRESULT hr;
if (SUCCEEDED(object->IsValid()))
{
if (NULL != instance)
{
*instance = object;
object->AddRef();
}
hr = S_OK;
}
else
hr = E_FAIL;
object->Release();
object = NULL;
if (NULL != reader)
reader->xmlreader_unregisterCallback(this);
return hr;
}
void LoginCommandParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
}
void LoginCommandParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (NULL != object)
object->SetParameter(xmltag, elementString.Get());
}
void LoginCommandParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void LoginCommandParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS LoginCommandParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,40 @@
#ifndef NULLSOFT_AUTH_LOGIN_COMMAND_PARSER_HEADER
#define NULLSOFT_AUTH_LOGIN_COMMAND_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./stringBuilder.h"
class obj_xml;
class LoginCommand;
class LoginCommandParser : public ifc_xmlreadercallback
{
public:
LoginCommandParser();
~LoginCommandParser();
public:
HRESULT Begin(obj_xml *reader, ifc_xmlreaderparams *params);
HRESULT End(obj_xml *reader, LoginCommand **instance);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
LoginCommand *object;
StringBuilder elementString;
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGIN_COMMAND_PARSER_HEADER

View File

@@ -0,0 +1,159 @@
#include "./commandWebAuth.h"
#include "./resultWebAuth.h"
#include "./common.h"
#include "../api.h"
#include "../../omBrowser/obj_ombrowser.h"
#include <api/service/waservicefactory.h>
LoginCommandWebAuth::LoginCommandWebAuth()
: ref(1), targetUrl(NULL)
{
}
LoginCommandWebAuth::~LoginCommandWebAuth()
{
LoginBox_FreeString(targetUrl);
}
HRESULT LoginCommandWebAuth::CreateInstance(LoginCommandWebAuth **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new LoginCommandWebAuth();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
ULONG LoginCommandWebAuth::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginCommandWebAuth::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginCommandWebAuth::GetType(GUID *commandUid)
{
if (NULL == commandUid) return E_INVALIDARG;
*commandUid = LCUID_WEBAUTH;
return S_OK;
}
HRESULT LoginCommandWebAuth::SetParameter(LPCWSTR pszKey, LPCWSTR pszValue)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, pszKey, -1, L"url", -1))
{
LoginBox_FreeString(targetUrl);
targetUrl = LoginBox_CopyString(pszValue);
}
return S_OK;
}
HRESULT LoginCommandWebAuth::IsValid()
{
if (NULL == targetUrl || L'\0' == *targetUrl)
return S_FALSE;
HRESULT hr = S_FALSE;
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(OBJ_OmBrowser);
if (NULL != sf)
{
obj_ombrowser *browserMngr = (obj_ombrowser*)sf->getInterface();
if (NULL != browserMngr)
{
hr = S_OK;
browserMngr->Release();
}
sf->Release();
}
return hr;
}
HRESULT LoginCommandWebAuth::IsIdentical(LoginCommand *test)
{
if (NULL == test)
return E_INVALIDARG;
GUID typeId;
if (FAILED(test->GetType(&typeId)) || FALSE == IsEqualGUID(LCUID_WEBAUTH, typeId))
return S_FALSE;
LoginCommandWebAuth *testWeb = (LoginCommandWebAuth*)test;
if(S_OK != LoginBox_IsStrEqInvI(targetUrl, testWeb->targetUrl))
return S_FALSE;
return S_OK;
}
HRESULT LoginCommandWebAuth::BeginLogin(LoginData *data, LoginResult::Callback callback, void *user, LoginResult **result)
{
HRESULT hr;
LoginResultWebAuth *webAuth;
hr = LoginResultWebAuth::CreateInstance(targetUrl, data, callback, user, &webAuth);
if (SUCCEEDED(hr))
{
if (NULL != result)
*result = webAuth;
else
webAuth->Release();
}
else
{
if (NULL != result)
*result = NULL;
}
return hr;
}
HRESULT LoginCommandWebAuth::EndLogin(LoginResult *result, INT *authCode, LoginCredentials **credentials)
{
if (NULL == result)
return E_INVALIDARG;
HRESULT hr = result->IsCompleted();
if (S_OK != hr)
{
HANDLE completed;
hr = result->GetWaitHandle(&completed);
if (SUCCEEDED(hr))
{
WaitForSingleObjectEx(completed, INFINITE, TRUE);
CloseHandle(completed);
}
}
if (SUCCEEDED(hr))
{
LoginResultWebAuth *webAuth;
hr = result->QueryInterface(LCUID_WEBAUTH, (void**)&webAuth);
if(SUCCEEDED(hr))
{
hr = webAuth->GetResult(authCode, credentials);
webAuth->Release();
}
}
return hr;
}
HRESULT LoginCommandWebAuth::RequestAbort(LoginResult *result, BOOL drop)
{
if (NULL == result) return E_INVALIDARG;
return result->RequestAbort(drop);
}

View File

@@ -0,0 +1,42 @@
#ifndef NULLSOFT_AUTH_LOGINCOMMAND_WEBAUTH_HEADER
#define NULLSOFT_AUTH_LOGINCOMMAND_WEBAUTH_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginCommand.h"
// {48F006E2-EC11-4171-833B-A9CD14F6D727}
static const GUID LCUID_WEBAUTH =
{ 0x48f006e2, 0xec11, 0x4171, { 0x83, 0x3b, 0xa9, 0xcd, 0x14, 0xf6, 0xd7, 0x27 } };
class LoginCommandWebAuth : public LoginCommand
{
protected:
LoginCommandWebAuth();
~LoginCommandWebAuth();
public:
static HRESULT CreateInstance(LoginCommandWebAuth **instance);
public:
ULONG AddRef();
ULONG Release();
HRESULT GetType(GUID *commandUid);
HRESULT SetParameter(LPCWSTR pszKey, LPCWSTR pszValue);
HRESULT IsValid();
HRESULT IsIdentical(LoginCommand *test);
HRESULT BeginLogin(LoginData *data, LoginResult::Callback callback, void *user, LoginResult **result);
HRESULT EndLogin(LoginResult *result, INT *authCode, LoginCredentials **credentials);
HRESULT RequestAbort(LoginResult *result, BOOL drop);
protected:
ULONG ref;
LPWSTR targetUrl;
};
#endif //NULLSOFT_AUTH_LOGINCOMMAND_WEBAUTH_HEADER

View File

@@ -0,0 +1,125 @@
#include "./commandWinampAuth.h"
#include "./resultWinampAuth.h"
LoginCommandWinampAuth::LoginCommandWinampAuth()
: ref(1)
{
}
LoginCommandWinampAuth::~LoginCommandWinampAuth()
{
}
HRESULT LoginCommandWinampAuth::CreateInstance(LoginCommandWinampAuth **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new LoginCommandWinampAuth();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
ULONG LoginCommandWinampAuth::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginCommandWinampAuth::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginCommandWinampAuth::GetType(GUID *commandUid)
{
if (NULL == commandUid) return E_INVALIDARG;
*commandUid = LCUID_WINAMPAUTH;
return S_OK;
}
HRESULT LoginCommandWinampAuth::SetParameter(LPCWSTR pszKey, LPCWSTR pszValue)
{
return E_NOTIMPL;
}
HRESULT LoginCommandWinampAuth::IsValid()
{
return S_OK;
}
HRESULT LoginCommandWinampAuth::IsIdentical(LoginCommand *test)
{
if (NULL == test)
return E_INVALIDARG;
GUID typeId;
if (FAILED(test->GetType(&typeId)) || FALSE == IsEqualGUID(LCUID_WINAMPAUTH, typeId))
return S_FALSE;
return S_OK;
}
HRESULT LoginCommandWinampAuth::BeginLogin(LoginData *data, LoginResult::Callback callback, void *user, LoginResult **result)
{
LoginResultWinampAuth *winampAuth;
HRESULT hr = LoginResultWinampAuth::CreateInstance(data, callback, user, &winampAuth);
if (SUCCEEDED(hr))
{
if (NULL != result)
*result = winampAuth;
else
winampAuth->Release();
}
else
{
if (NULL != result)
*result = NULL;
}
return hr;
}
HRESULT LoginCommandWinampAuth::EndLogin(LoginResult *result, INT *authCode, LoginCredentials **credentials)
{
if (NULL == result)
return E_INVALIDARG;
HRESULT hr = result->IsCompleted();
if (S_OK != hr)
{
HANDLE completed;
hr = result->GetWaitHandle(&completed);
if (SUCCEEDED(hr))
{
WaitForSingleObjectEx(completed, INFINITE, TRUE);
CloseHandle(completed);
}
}
if (SUCCEEDED(hr))
{
LoginResultWinampAuth *winampAuth;
hr = result->QueryInterface(LCUID_WINAMPAUTH, (void**)&winampAuth);
if(SUCCEEDED(hr))
{
hr = winampAuth->GetResult(authCode, credentials);
winampAuth->Release();
}
}
return hr;
}
HRESULT LoginCommandWinampAuth::RequestAbort(LoginResult *result, BOOL drop)
{
if (NULL == result) return E_INVALIDARG;
return result->RequestAbort(drop);
}

View File

@@ -0,0 +1,44 @@
#ifndef NULLSOFT_AUTH_LOGINCOMMAND_WINAMPAUTH_HEADER
#define NULLSOFT_AUTH_LOGINCOMMAND_WINAMPAUTH_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginCommand.h"
// {36B883C8-5400-4d43-89EA-96B1CBEFC605}
static const GUID LCUID_WINAMPAUTH =
{ 0x36b883c8, 0x5400, 0x4d43, { 0x89, 0xea, 0x96, 0xb1, 0xcb, 0xef, 0xc6, 0x5 } };
class LoginCommandWinampAuth : public LoginCommand
{
protected:
LoginCommandWinampAuth();
~LoginCommandWinampAuth();
public:
static HRESULT CreateInstance(LoginCommandWinampAuth **instance);
public:
ULONG AddRef();
ULONG Release();
HRESULT GetType(GUID *commandUid);
HRESULT SetParameter(LPCWSTR pszKey, LPCWSTR pszValue);
HRESULT IsValid();
HRESULT IsIdentical(LoginCommand *test);
HRESULT BeginLogin(LoginData *data, LoginResult::Callback callback, void *user, LoginResult **result);
HRESULT EndLogin(LoginResult *result, INT *authCode, LoginCredentials **credentials);
HRESULT RequestAbort(LoginResult *result, BOOL drop);
protected:
ULONG ref;
};
#endif //NULLSOFT_AUTH_LOGINCOMMAND_WINAMPAUTH_HEADER

View File

@@ -0,0 +1,618 @@
#include "./common.h"
#include "../api.h"
#include "../../winamp/accessibilityConfigGroup.h"
#include <shlwapi.h>
#include <strsafe.h>
LPWSTR LoginBox_MallocString(size_t cchLen)
{
return (LPWSTR)calloc(cchLen, sizeof(WCHAR));
}
void LoginBox_FreeString(LPWSTR pszString)
{
if (NULL != pszString)
{
free(pszString);
}
}
void LoginBox_FreeStringSecure(LPWSTR pszString)
{
if (NULL != pszString)
{
size_t size = LoginBox_GetAllocSize(pszString);
if (0 != size)
SecureZeroMemory(pszString, size);
free(pszString);
}
}
LPWSTR LoginBox_ReAllocString(LPWSTR pszString, size_t cchLen)
{
return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen);
}
LPWSTR LoginBox_CopyString(LPCWSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenW(pszSource) + 1;
LPWSTR copy = LoginBox_MallocString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource);
}
return copy;
}
LPSTR LoginBox_MallocAnsiString(size_t cchLen)
{
return (LPSTR)calloc(cchLen, sizeof(CHAR));
}
LPSTR LoginBox_CopyAnsiString(LPCSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenA(pszSource) + 1;
LPSTR copy = LoginBox_MallocAnsiString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource);
}
return copy;
}
void LoginBox_FreeAnsiString(LPSTR pszString)
{
LoginBox_FreeString((LPWSTR)pszString);
}
void LoginBox_FreeAnsiStringSecure(LPSTR pszString)
{
LoginBox_FreeStringSecure((LPWSTR)pszString);
}
size_t LoginBox_GetAllocSize(void *memory)
{
return (NULL != memory) ? _msize(memory) : 0;
}
size_t LoginBox_GetStringMax(LPWSTR pszString)
{
return LoginBox_GetAllocSize(pszString)/sizeof(WCHAR);
}
size_t LoginBox_GetAnsiStringMax(LPSTR pszString)
{
return LoginBox_GetAllocSize(pszString)/sizeof(CHAR);
}
HRESULT LoginBox_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar, LPSTR *ppResult)
{
if (NULL == ppResult)
return E_POINTER;
INT resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cchWideChar > 0)
resultMax++;
*ppResult = LoginBox_MallocAnsiString(resultMax);
if (NULL == *ppResult) return E_OUTOFMEMORY;
resultMax = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, *ppResult, resultMax, lpDefaultChar, lpUsedDefaultChar);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
LoginBox_FreeAnsiString(*ppResult);
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cchWideChar > 0)
(*ppResult)[resultMax] = '\0';
return S_OK;
}
HRESULT LoginBox_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte, LPWSTR *ppResult)
{
if (NULL == ppResult)
return E_POINTER;
INT resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cbMultiByte > 0)
resultMax++;
*ppResult = LoginBox_MallocString(resultMax);
if (NULL == *ppResult) return E_OUTOFMEMORY;
resultMax = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, *ppResult, resultMax);
if (0 == resultMax)
{
DWORD errorCode = GetLastError();
LoginBox_FreeString(*ppResult);
*ppResult = NULL;
return HRESULT_FROM_WIN32(errorCode);
}
if (cbMultiByte > 0)
(*ppResult)[resultMax] = L'\0';
return S_OK;
}
HRESULT LoginBox_GetConfigPath(LPWSTR pszConfig, BOOL fEnsureExist)
{
if (NULL == pszConfig)
return E_INVALIDARG;
LPCWSTR pszWinamp;
pszWinamp = (NULL != WASABI_API_APP) ? WASABI_API_APP->path_getUserSettingsPath(): NULL;
if (NULL == pszWinamp)
return E_FAIL;
if (NULL == PathCombine(pszConfig, pszWinamp, L"Plugins\\loginBox"))
return E_FAIL;
if (FALSE != fEnsureExist)
{
HRESULT hr;
hr = LoginBox_EnsurePathExist(pszConfig);
if (FAILED(hr)) return hr;
}
return S_OK;
}
HRESULT LoginBox_EnsurePathExist(LPCWSTR pszDirectory)
{
DWORD ec = ERROR_SUCCESS;
UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
if (0 == CreateDirectory(pszDirectory, NULL))
{
ec = GetLastError();
if (ERROR_PATH_NOT_FOUND == ec)
{
LPCWSTR pszBlock = pszDirectory;
WCHAR szBuffer[MAX_PATH] = {0};
LPCTSTR pszCursor = PathFindNextComponent(pszBlock);
ec = (pszCursor == pszBlock || S_OK != StringCchCopyN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock))) ?
ERROR_INVALID_NAME : ERROR_SUCCESS;
pszBlock = pszCursor;
while (ERROR_SUCCESS == ec && NULL != (pszCursor = PathFindNextComponent(pszBlock)))
{
if (pszCursor == pszBlock || S_OK != StringCchCatN(szBuffer, ARRAYSIZE(szBuffer), pszBlock, (pszCursor - pszBlock)))
ec = ERROR_INVALID_NAME;
if (ERROR_SUCCESS == ec && !CreateDirectory(szBuffer, NULL))
{
ec = GetLastError();
if (ERROR_ALREADY_EXISTS == ec) ec = ERROR_SUCCESS;
}
pszBlock = pszCursor;
}
}
if (ERROR_ALREADY_EXISTS == ec)
ec = ERROR_SUCCESS;
}
SetErrorMode(errorMode);
SetLastError(ec);
return HRESULT_FROM_WIN32(ec);
}
HRESULT LoginBox_GetWindowText(HWND hwnd, LPWSTR *ppszText, UINT *pcchText)
{
if (NULL == ppszText) return E_POINTER;
if (NULL == hwnd) return E_INVALIDARG;
UINT cchText = (UINT)SNDMSG(hwnd, WM_GETTEXTLENGTH, 0, 0L);
cchText++;
*ppszText = LoginBox_MallocString(cchText);
if (NULL == *ppszText)
{
if (NULL != pcchText) *pcchText = 0;
return E_OUTOFMEMORY;
}
cchText = (UINT)SNDMSG(hwnd, WM_GETTEXT, (WPARAM)cchText, (LPARAM)*ppszText);
if (NULL != pcchText)
*pcchText = cchText;
return S_OK;
}
BOOL LoginBox_PrintWindow(HWND hwnd, HDC hdc, UINT flags)
{
typedef BOOL (WINAPI *PRINTWINDOW)(HWND /*hwnd*/, HDC /*hdc*/, UINT /*nFlags*/);
static PRINTWINDOW printWindow = NULL;
static HMODULE moduleUser32 = NULL;
if (NULL == moduleUser32)
{
moduleUser32 = GetModuleHandle(L"USER32");
if (NULL == moduleUser32) return FALSE;
printWindow = (PRINTWINDOW)GetProcAddress(moduleUser32, "PrintWindow");
}
return (NULL != printWindow && FALSE != printWindow(hwnd, hdc, flags));
}
BOOL LoginBox_MessageBeep(UINT beepType)
{
BOOL result = FALSE;
ifc_configitem *beepEnabled = AGAVE_API_CONFIG->GetItem(accessibilityConfigGroupGUID, L"modalbeep");
if (NULL != beepEnabled)
{
if (false != beepEnabled->GetBool())
{
result = MessageBeep(beepType);
}
beepEnabled->Release();
}
return result;
}
HRESULT LoginBox_IsStringEqualEx(LCID locale, BOOL ignoreCase, LPCWSTR str1, LPCWSTR str2)
{
if ((NULL == str1) != (NULL == str2))
return S_FALSE;
if (NULL != str1 && CSTR_EQUAL != CompareString(locale, (FALSE != ignoreCase) ? NORM_IGNORECASE : 0, str1, -1, str2, -1))
return S_FALSE;
return S_OK;
}
UINT LoginBox_GetCurrentTime()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
if(FALSE == SystemTimeToFileTime(&st, &ft))
return 0;
ULARGE_INTEGER t1;
t1.LowPart = ft.dwLowDateTime;
t1.HighPart = ft.dwHighDateTime;
return (UINT)((t1.QuadPart - 116444736000000000) / 10000000);
}
HRESULT LoginBox_GetCurrentLang(LPSTR *ppLang)
{
if (NULL == ppLang)
return E_POINTER;
if (NULL == WASABI_API_LNG)
return E_UNEXPECTED;
LPCWSTR lang = WASABI_API_LNG->GetLanguageIdentifier(LANG_LANG_CODE);
if (NULL != lang && L'\0' != *lang)
return LoginBox_WideCharToMultiByte(CP_UTF8, 0, lang, -1, NULL, NULL, ppLang);
*ppLang = NULL;
return S_OK;
}
HDWP LoginBox_LayoutButtonBar(HDWP hdwp, HWND hwnd, const INT *buttonList, UINT buttonCount, const RECT *prcClient, LONG buttonHeight, LONG buttonSpace, BOOL fRedraw, RECT *prcResult)
{
if (NULL == hdwp && NULL == prcClient)
return NULL;
RECT rect;
CopyRect(&rect, prcClient);
LONG top = rect.bottom - buttonHeight;
if (top < rect.top) top = rect.top;
LONG height = rect.bottom - top;
LONG width;
LONG right = rect.right;
if (NULL == buttonList || 0 == buttonCount)
{
if (NULL != prcResult)
SetRect(prcResult, right, top, rect.right, top + height);
return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
}
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
WCHAR szText[256] = {0};
INT cchText;
HFONT font(NULL), fontOrig;
SIZE textSize;
RECT buttonRect;
while(buttonCount--)
{
HWND hControl = GetDlgItem(hwnd, buttonList[buttonCount]);
if (NULL == hControl || 0 == (WS_VISIBLE & GetWindowStyle(hControl)) ||
FALSE == GetWindowRect(hControl, &buttonRect))
{
continue;
}
if (right != rect.right)
right -= buttonSpace;
width = buttonRect.right - buttonRect.left;
cchText = (INT)SendMessage(hControl, WM_GETTEXT, (WPARAM)ARRAYSIZE(szText), (LPARAM)szText);
if (cchText > 0)
{
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL != hdc)
{
if (NULL == font)
font = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
fontOrig = (HFONT)SelectObject(hdc, font);
if (FALSE != GetTextExtentPoint32W(hdc, szText, cchText, &textSize))
{
width = textSize.cx + 4*LoginBox_GetAveCharWidth(hdc);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hControl, hdc);
}
}
if (width < 75)
width = 75;
if (NULL != hdwp)
{
hdwp = DeferWindowPos(hdwp, hControl, NULL, right - width, top, width, height, flags);
if (NULL == hdwp) return NULL;
}
right -= width;
}
if (NULL != prcResult)
SetRect(prcResult, right, top, rect.right, top + height);
return (NULL != hdwp) ? hdwp :(HDWP)TRUE;
}
BYTE LoginBox_GetSysFontQuality()
{
BOOL smoothingEnabled;
if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
FALSE == smoothingEnabled)
{
return DEFAULT_QUALITY;
}
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (FALSE == GetVersionEx(&vi))
return DEFAULT_QUALITY;
if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
{
UINT smootingType;
if (FALSE == SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
return DEFAULT_QUALITY;
if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
return CLEARTYPE_QUALITY;
}
return ANTIALIASED_QUALITY;
}
INT LoginBox_GetAveStrWidth(HDC hdc, INT cchLen)
{
const char szTest[] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l', 'm','n','o','p','q','r','s','t','u','v','w','x','y','z'
};
SIZE textSize;
if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
return 0;
INT result;
if (1 == cchLen)
{
result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
}
else
{
result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
if (0 != result)
{
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
result += tm.tmOverhang;
}
}
return result;
}
INT LoginBox_GetAveCharWidth(HDC hdc)
{
return LoginBox_GetAveStrWidth(hdc, 1);
}
BOOL LoginBox_GetWindowBaseUnits(HWND hwnd, INT *pBaseUnitX, INT *pBaseUnitY)
{
INT baseunitX(0), baseunitY(0);
BOOL result = FALSE;
if (NULL != hwnd)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
baseunitY = tm.tmHeight;
baseunitX = LoginBox_GetAveCharWidth(hdc);
result = TRUE;
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
}
if (NULL != pBaseUnitX) *pBaseUnitX = baseunitX;
if (NULL != pBaseUnitY) *pBaseUnitY = baseunitY;
return result;
}
INT LoginBox_GetWindowTextHeight(HWND hwnd, INT paddingDlgUnit)
{
if (NULL == hwnd) return 0;
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return 0;
INT height = 0;
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
height = tm.tmHeight;
if (0 != paddingDlgUnit)
height += MulDiv(2 * paddingDlgUnit, tm.tmHeight, 8);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
return height;
}
BOOL LoginBox_GetWindowTextSize(HWND hwnd, INT idealWidth, INT *pWidth, INT *pHeight)
{
INT width(0), height(0);
BOOL result = FALSE;
if (NULL != hwnd)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
LPWSTR pszText;
UINT cchText;
if (SUCCEEDED(LoginBox_GetWindowText(hwnd, &pszText, &cchText)))
{
if (0 == cchText)
{
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdc, &tm))
{
height = tm.tmHeight;
width = 0;
result = TRUE;
}
}
else
{
RECT rect;
SetRect(&rect, 0, 0, idealWidth, 0);
if (0 != DrawText(hdc, pszText, cchText, &rect, DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK))
{
width = rect.right - rect.left;
height = rect.bottom - rect.top;
result = TRUE;
}
}
LoginBox_FreeString(pszText);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
}
if (NULL != pWidth) *pWidth = width;
if (NULL != pHeight) *pHeight = height;
return result;
}
BOOL LoginBox_OpenUrl(HWND hOwner, LPCWSTR pszUrl, BOOL forceExternal)
{
if (NULL == WASABI_API_WINAMP)
return FALSE;
HCURSOR hCursor = LoadCursor(NULL, IDC_APPSTARTING);
if (NULL != hCursor)
hCursor = SetCursor(hCursor);
BOOL result;
if (FALSE != forceExternal)
{
HINSTANCE hInst = ShellExecute(hOwner, L"open", pszUrl, NULL, NULL, SW_SHOWNORMAL);
result = ((INT_PTR)hInst > 32) ? TRUE: FALSE;
}
else
{
HRESULT hr = WASABI_API_WINAMP->OpenUrl(hOwner, pszUrl);
result = SUCCEEDED(hr);
}
if (NULL != hCursor)
SetCursor(hCursor);
return result;
}

View File

@@ -0,0 +1,96 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_COMMON_HEADER
#define NULLSOFT_AUTH_LOGINBOX_COMMON_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(blah) (sizeof(blah)/sizeof(*blah))
#endif
#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
#ifndef LONGX86
#ifdef _WIN64
#define LONGX86 LONG_PTR
#else /*_WIN64*/
#define LONGX86 LONG
#endif /*_WIN64*/
#endif // LONGX86
#ifdef __cplusplus
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#else
#define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
#endif // __cplusplus
#define MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
#ifndef GetWindowStyle
#define GetWindowStyle(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_STYLE))
#endif //GetWindowStyle
#ifndef GetWindowStyleEx
#define GetWindowStyleEx(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_EXSTYLE))
#endif //GetWindowStyleEx
LPWSTR LoginBox_MallocString(size_t cchLen);
void LoginBox_FreeString(LPWSTR pszString);
void LoginBox_FreeStringSecure(LPWSTR pszString);
LPWSTR LoginBox_ReAllocString(LPWSTR pszString, size_t cchLen);
LPWSTR LoginBox_CopyString(LPCWSTR pszSource);
LPSTR LoginBox_MallocAnsiString(size_t cchLen);
LPSTR LoginBox_CopyAnsiString(LPCSTR pszSource);
void LoginBox_FreeAnsiString(LPSTR pszString);
void LoginBox_FreeAnsiStringSecure(LPSTR pszString);
size_t LoginBox_GetAllocSize(void *memory);
size_t LoginBox_GetStringMax(LPWSTR pszString);
size_t LoginBox_GetAnsiStringMax(LPSTR pszString);
HRESULT LoginBox_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar, LPSTR *ppResult);
HRESULT LoginBox_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte, LPWSTR *ppResult);
HRESULT LoginBox_GetWindowText(HWND hwnd, LPWSTR *ppszText, UINT *pcchText);
HRESULT LoginBox_GetConfigPath(LPWSTR pszConfig, BOOL fEnsureExist);
HRESULT LoginBox_EnsurePathExist(LPCWSTR pszDirectory);
BOOL LoginBox_PrintWindow(HWND hwnd, HDC hdc, UINT flags);
BOOL LoginBox_MessageBeep(UINT beepType);
HRESULT LoginBox_IsStringEqualEx(LCID locale, BOOL ignoreCase, LPCWSTR str1, LPCWSTR str2);
#define LoginBox_IsStrEq(str1, str2)\
LoginBox_IsStringEqualEx(LOCALE_USER_DEFAULT, FALSE, str1, str2)
#define LoginBox_IsStrEqI(str1, str2)\
LoginBox_IsStringEqualEx(LOCALE_USER_DEFAULT, TRUE, str1, str2)
#define LoginBox_IsStrEqInv(str1, str2)\
LoginBox_IsStringEqualEx(CSTR_INVARIANT, FALSE, str1, str2)
#define LoginBox_IsStrEqInvI(str1, str2)\
LoginBox_IsStringEqualEx(CSTR_INVARIANT, TRUE, str1, str2)
UINT LoginBox_GetCurrentTime();
HRESULT LoginBox_GetCurrentLang(LPSTR *ppLang);
HDWP LoginBox_LayoutButtonBar(HDWP hdwp, HWND hwnd, const INT *buttonList, UINT buttonCount, const RECT *prcClient, LONG buttonHeight, LONG buttonSpace, BOOL fRedraw, RECT *prcResult);
BYTE LoginBox_GetSysFontQuality();
INT LoginBox_GetAveStrWidth(HDC hdc, INT cchLen);
INT LoginBox_GetAveCharWidth(HDC hdc);
BOOL LoginBox_GetWindowBaseUnits(HWND hwnd, INT *pBaseUnitX, INT *pBaseUnitY);
INT LoginBox_GetWindowTextHeight(HWND hwnd, INT paddingDlgUnit);
BOOL LoginBox_GetWindowTextSize(HWND hwnd, INT idealWidth, INT *pWidth, INT *pHeight);
BOOL LoginBox_OpenUrl(HWND hOwner, LPCWSTR pszUrl, BOOL forceExternal);
#endif //NULLSOFT_AUTH_LOGINBOX_COMMON_HEADER

View File

@@ -0,0 +1,46 @@
#include "./dataAddress.h"
#include "./common.h"
#include <strsafe.h>
LoginDataAddress::LoginDataAddress(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszAddress)
: LoginData(pRealm, hPage, hLoginbox), address(NULL)
{
address = LoginBox_CopyString(pszAddress);
}
LoginDataAddress::~LoginDataAddress()
{
LoginBox_FreeString(address);
}
HRESULT LoginDataAddress::CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszAddress, LoginDataAddress **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hPage || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginDataAddress(pRealm, hPage, hLoginbox, pszAddress);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT LoginDataAddress::QueryInterface(REFIID riid, void** ppObject)
{
if (NULL == ppObject)
return E_POINTER;
if (IsEqualIID(riid, IID_LoginDataAddress))
{
*ppObject = static_cast<LoginDataAddress*>(this);
if (NULL == *ppObject) return E_UNEXPECTED;
AddRef();
return S_OK;
}
return __super::QueryInterface(riid, ppObject);
}
LPCWSTR LoginDataAddress::GetAddress()
{
return address;
}

View File

@@ -0,0 +1,34 @@
#ifndef NULLSOFT_AUTH_LOGINDATA_ADDRESS_HEADER
#define NULLSOFT_AUTH_LOGINDATA_ADDRESS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginData.h"
// {830B9FCD-3A09-4485-8BA6-1A6B8F10ED39}
static const GUID IID_LoginDataAddress =
{ 0x830b9fcd, 0x3a09, 0x4485, { 0x8b, 0xa6, 0x1a, 0x6b, 0x8f, 0x10, 0xed, 0x39 } };
class LoginDataAddress : public LoginData
{
protected:
LoginDataAddress(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszAddress);
~LoginDataAddress();
public:
static HRESULT CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszAddress, LoginDataAddress **instance);
public:
virtual HRESULT QueryInterface(REFIID riid, void** ppObject);
LPCWSTR GetAddress();
protected:
LPWSTR address;
};
#endif //NULLSOFT_AUTH_LOGINDATA_ADDRESS_HEADER

View File

@@ -0,0 +1,98 @@
#include "./dataCredentials.h"
#include "./common.h"
#include <strsafe.h>
LoginDataCredentials::LoginDataCredentials(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszUsername, LPCWSTR pszPassword)
: LoginData(pRealm, hPage, hLoginbox), username(NULL), password(NULL), context(NULL), passcode(NULL)
{
username = LoginBox_CopyString(pszUsername);
password = LoginBox_CopyString(pszPassword);
}
LoginDataCredentials::~LoginDataCredentials()
{
LoginBox_FreeStringSecure(username);
LoginBox_FreeStringSecure(password);
LoginBox_FreeStringSecure(passcode);
LoginBox_FreeAnsiStringSecure(context);
}
HRESULT LoginDataCredentials::CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszUsername, LPCWSTR pszPassword, LoginDataCredentials **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hPage || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginDataCredentials(pRealm, hPage, hLoginbox, pszUsername, pszPassword);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT LoginDataCredentials::QueryInterface(REFIID riid, void** ppObject)
{
if (NULL == ppObject)
return E_POINTER;
if (IsEqualIID(riid, IID_LoginDataCredentials))
{
*ppObject = static_cast<LoginDataCredentials*>(this);
if (NULL == *ppObject) return E_UNEXPECTED;
AddRef();
return S_OK;
}
return __super::QueryInterface(riid, ppObject);
}
LPCWSTR LoginDataCredentials::GetUsername()
{
return username;
}
LPCWSTR LoginDataCredentials::GetPassword()
{
return password;
}
HRESULT LoginDataCredentials::SetContext(LPCSTR pszContext)
{
LoginBox_FreeAnsiStringSecure(context);
if (NULL == pszContext)
{
context = NULL;
}
else
{
context = LoginBox_CopyAnsiString(pszContext);
if (NULL == context)
return E_OUTOFMEMORY;
}
return S_OK;
}
LPCSTR LoginDataCredentials::GetContext()
{
return context;
}
HRESULT LoginDataCredentials::SetPasscode(LPCWSTR pszPasscode)
{
LoginBox_FreeStringSecure(passcode);
if (NULL == pszPasscode)
{
passcode = NULL;
}
else
{
passcode = LoginBox_CopyString(pszPasscode);
if (NULL == passcode)
return E_OUTOFMEMORY;
}
return S_OK;
}
LPCWSTR LoginDataCredentials::GetPasscode()
{
return passcode;
}

View File

@@ -0,0 +1,43 @@
#ifndef NULLSOFT_AUTH_LOGINDATA_CREDENTIALS_HEADER
#define NULLSOFT_AUTH_LOGINDATA_CREDENTIALS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginData.h"
// {15D82B0E-A557-4497-808D-CB68F2C9C33A}
static const GUID IID_LoginDataCredentials =
{ 0x15d82b0e, 0xa557, 0x4497, { 0x80, 0x8d, 0xcb, 0x68, 0xf2, 0xc9, 0xc3, 0x3a } };
class LoginDataCredentials : public LoginData
{
protected:
LoginDataCredentials(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszUsername, LPCWSTR pszPassword);
~LoginDataCredentials();
public:
static HRESULT CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LPCWSTR pszUsername, LPCWSTR pszPassword, LoginDataCredentials **instance);
public:
virtual HRESULT QueryInterface(REFIID riid, void** ppObject);
LPCWSTR GetUsername();
LPCWSTR GetPassword();
HRESULT SetContext(LPCSTR pszContext);
LPCSTR GetContext();
HRESULT SetPasscode(LPCWSTR pszPasscode);
LPCWSTR GetPasscode();
protected:
LPWSTR username;
LPWSTR password;
LPWSTR passcode;
LPSTR context;
};
#endif //NULLSOFT_AUTH_LOGINDATA_CREDENTIALS_HEADER

View File

@@ -0,0 +1,268 @@
#include "./common.h"
#include "./download.h"
#include "./downloadResult.h"
#include "../api.h"
#include <api/service/waservicefactory.h>
#include "./providerLoader.h"
#include "./providerEnumerator.h"
#include <shlwapi.h>
LoginDownload::LoginDownload()
{
}
LoginDownload::~LoginDownload()
{
}
HRESULT LoginDownload::Begin(LPCWSTR pszUrl, UINT type, LoginDownloadResult::Callback callback, void *data, LoginStatus *pStatus, LoginDownloadResult **result)
{
if (NULL == result) return E_POINTER;
*result = NULL;
if (NULL == pszUrl || L'\0' == *pszUrl)
return E_INVALIDARG;
HRESULT hr;
LPSTR addressAnsi;
hr = LoginBox_WideCharToMultiByte(CP_UTF8, 0, pszUrl, -1, NULL, NULL, &addressAnsi);
if (SUCCEEDED(hr))
{
if (NULL != WASABI_API_SVC)
{
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(DownloadManagerGUID);
api_downloadManager *manager = (NULL != sf) ? (api_downloadManager *)sf->getInterface() : NULL;
if (NULL == manager)
hr = E_UNEXPECTED;
else
{
hr = LoginDownloadResult::CreateInstance(manager, type, callback, data, pStatus, result);
if (SUCCEEDED(hr))
{
if (0 == manager->DownloadEx(addressAnsi, *result, api_downloadManager::DOWNLOADEX_TEMPFILE))
{
(*result)->Release();
*result = NULL;
hr = E_FAIL;
}
}
else
{
sf->releaseInterface(manager);
}
}
}
}
LoginBox_FreeAnsiString(addressAnsi);
return hr;
}
HRESULT LoginDownload::End(LoginDownloadResult *result, BSTR *bstrFileName)
{
if (NULL != bstrFileName)
*bstrFileName = NULL;
if (NULL == result) return E_INVALIDARG;
HRESULT hr;
UINT state;
if (FAILED(result->GetState(&state)) || LoginDownloadResult::stateCompleted != state)
{
HANDLE completed;
hr = result->GetWaitHandle(&completed);
if (FAILED(hr)) return hr;
while(WAIT_OBJECT_0 != WaitForSingleObjectEx(completed, INFINITE, TRUE));
CloseHandle(completed);
}
UINT type;
hr = result->GetType(&type);
if (FAILED(hr)) return hr;
switch(type)
{
case LoginDownloadResult::typeProviderList:
hr = SaveProviderList(result, bstrFileName);
break;
case LoginDownloadResult::typeImage:
hr = SaveImage(result, bstrFileName);
break;
case LoginDownloadResult::typeUnknown:
hr = E_NOTIMPL;
break;
}
return hr;
}
HRESULT LoginDownload::SaveProviderList(LoginDownloadResult *result, BSTR *bstrFileName)
{
if (NULL == result)
return E_INVALIDARG;
HRESULT hr;
LPCWSTR pszSource;
hr = result->GetFile(&pszSource);
if (FAILED(hr)) return hr;
WCHAR szTarget[2048] = {0};
hr = LoginBox_GetConfigPath(szTarget, TRUE);
if (FAILED(hr)) return hr;
if (FALSE == PathAppend(szTarget, L"loginProviders.xml"))
return E_FAIL;
if (S_OK == IsBinaryEqual(pszSource, szTarget))
hr = S_FALSE;
else
{
// validate source
LoginProviderEnumerator *enumerator;
LoginProviderLoader loader;
if (FAILED(loader.ReadXml(pszSource, &enumerator, NULL)))
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
else
{
enumerator->Release();
if (FALSE == CopyFile(pszSource, szTarget, FALSE))
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
}
else
hr = S_OK;
}
}
if (NULL != bstrFileName)
*bstrFileName = (SUCCEEDED(hr)) ? SysAllocString(szTarget) : NULL;
return hr;
}
HRESULT LoginDownload::SaveImage(LoginDownloadResult *result, BSTR *bstrFileName)
{
if (NULL == result)
return E_INVALIDARG;
HRESULT hr;
LPCWSTR pszSource;
hr = result->GetFile(&pszSource);
if (FAILED(hr)) return hr;
WCHAR szTarget[2048] = {0};
hr = LoginBox_GetConfigPath(szTarget, TRUE);
if (FAILED(hr)) return hr;
CHAR szFileAnsi[MAX_PATH] = {0}, szUrlAnsi[2096] = {0};
hr = result->CreateDownloadFileName(szFileAnsi, ARRAYSIZE(szFileAnsi));
if (FAILED(hr)) return hr;
hr = result->GetUrl(szUrlAnsi, ARRAYSIZE(szUrlAnsi));
if (FAILED(hr)) return hr;
LPWSTR pszFile;
hr = LoginBox_MultiByteToWideChar(CP_UTF8, 0, szFileAnsi, -1, &pszFile);
if (FAILED(hr)) return hr;
if (FALSE == PathAppend(szTarget, pszFile))
hr = E_FAIL;
else if (FALSE == CopyFile(pszSource, szTarget, FALSE))
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
}
if (NULL != bstrFileName)
*bstrFileName = SysAllocString(szTarget);
LoginBox_FreeString(pszFile);
return hr;
}
HRESULT LoginDownload::IsBinaryEqual(LPCWSTR pszFile1, LPCWSTR pszFile2)
{
HRESULT hr;
HANDLE hFile1, hFile2;
hFile1 = CreateFile(pszFile1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile1)
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
}
else hr = S_OK;
if (SUCCEEDED(hr))
{
hFile2 = CreateFile(pszFile2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile2)
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
}
}
else
hFile2 = INVALID_HANDLE_VALUE;
if (SUCCEEDED(hr))
{
// check sizes;
LARGE_INTEGER size1, size2;
if (FALSE == GetFileSizeEx(hFile1, &size1) || FALSE == GetFileSizeEx(hFile2, &size2))
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
}
else
{
if (size1.QuadPart == size2.QuadPart)
{
// compare data
BYTE szBuffer1[4096] = {0}, szBuffer2[4096] = {0};
for(;;)
{
DWORD read1 = 0, read2 = 0;
if (FALSE == ReadFile(hFile1, szBuffer1, ARRAYSIZE(szBuffer1), &read1, NULL) ||
FALSE == ReadFile(hFile2, szBuffer2, ARRAYSIZE(szBuffer2), &read2, NULL))
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
break;
}
if (0 == read1 || 0 == read2)
{
hr = (read1 == read2) ? S_OK : S_FALSE;
break;
}
if(read1 != read2 || 0 != memcmp(szBuffer1, szBuffer2, read1))
{
hr = S_FALSE;
break;
}
}
}
else
hr = S_FALSE;
}
}
if (INVALID_HANDLE_VALUE != hFile1)
CloseHandle(hFile1);
if (INVALID_HANDLE_VALUE != hFile2)
CloseHandle(hFile2);
return hr;
}

View File

@@ -0,0 +1,30 @@
#ifndef NULLSOFT_AUTH_LOGIN_DOWNLOAD_HEADER
#define NULLSOFT_AUTH_LOGIN_DOWNLOAD_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./downloadResult.h"
class LoginDownload
{
public:
LoginDownload();
~LoginDownload();
public:
HRESULT Begin(LPCWSTR pszUrl, UINT type, LoginDownloadResult::Callback callback, void *data, LoginStatus *status, LoginDownloadResult **result);
HRESULT End(LoginDownloadResult *result, BSTR *bstrFileName); // return S_FALSE if files binary indentical
private:
HRESULT SaveProviderList(LoginDownloadResult *result, BSTR *bstrFileName);
HRESULT SaveImage(LoginDownloadResult *result, BSTR *bstrFileName);
HRESULT IsBinaryEqual(LPCWSTR pszFile1, LPCWSTR pszFile2);
};
#endif //NULLSOFT_AUTH_LOGIN_DOWNLOAD_HEADER

View File

@@ -0,0 +1,435 @@
#include "./downloadResult.h"
#include "./loginStatus.h"
#include "../api.h"
#include "../resource.h"
#include "../jnetlib/api_httpget.h"
#include <strsafe.h>
LoginDownloadResult::LoginDownloadResult(api_downloadManager *pManager, UINT uType, Callback fnCallback, void *pData, LoginStatus *pStatus)
: ref(1), manager(pManager), flags(0), callback(fnCallback), data(pData),
address(NULL), result(api_downloadManager::TICK_NODATA),
cookie(0), completed(NULL), status(pStatus), statusCookie((UINT)-1)
{
InitializeCriticalSection(&lock);
SetType(uType);
SetState(stateInitializing);
if (NULL != status)
status->AddRef();
if (NULL != manager)
manager->AddRef();
}
LoginDownloadResult::~LoginDownloadResult()
{
EnterCriticalSection(&lock);
if(NULL != manager)
{
if (0 != cookie)
{
manager->ReleaseDownload(cookie);
cookie = 0;
}
manager->Release();
}
if (NULL != completed)
CloseHandle(completed);
if (NULL != address)
free(address);
if (NULL != status)
{
if (((UINT)-1) != statusCookie)
status->Remove(statusCookie);
status->Release();
}
LeaveCriticalSection(&lock);
DeleteCriticalSection(&lock);
}
HRESULT LoginDownloadResult::CreateInstance(api_downloadManager *pManager, UINT uType, Callback fnCallback, void *pData, LoginStatus *pStatus, LoginDownloadResult **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == pManager)
{
*instance = NULL;
return E_INVALIDARG;
}
*instance = new LoginDownloadResult(pManager, uType, fnCallback, pData, pStatus);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
size_t LoginDownloadResult::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t LoginDownloadResult::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int LoginDownloadResult::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
*object = NULL;
return E_NOINTERFACE;
}
void LoginDownloadResult::SetState(UINT uState)
{
flags = (flags & ~stateMask) | (uState & stateMask);
}
void LoginDownloadResult::SetType(UINT uType)
{
flags = (flags & ~typeMask) | (uType & typeMask);
}
void LoginDownloadResult::SetFlags(UINT uFlags, UINT uMask)
{
uMask &= flagsMask;
flags = (flags & ~uMask) | (uFlags & uMask);
}
HRESULT LoginDownloadResult::GetState(UINT *state)
{
if (NULL == state)
return E_POINTER;
EnterCriticalSection(&lock);
*state = (flags & stateMask);
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginDownloadResult::GetType(UINT *type)
{
if (NULL == type)
return E_POINTER;
EnterCriticalSection(&lock);
*type = (flags & typeMask);
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginDownloadResult::GetFile(LPCWSTR *ppszPath)
{
EnterCriticalSection(&lock);
HRESULT hr;
if (NULL == cookie || NULL == manager)
{
hr = E_UNEXPECTED;
}
else if (stateCompleted != (stateMask & flags))
{
hr = E_DWNLD_BUSY;
}
else
{
switch(result)
{
case api_downloadManager::TICK_SUCCESS: hr = E_DWNLD_OK; break;
case api_downloadManager::TICK_FAILURE: hr = (0 != (flagUserAbort & flags)) ? E_DWNLD_ABORT : E_DWNLD_FAIL; break;
case api_downloadManager::TICK_TIMEOUT: hr = E_DWNLD_TIMEOUT; break;
case api_downloadManager::TICK_CANT_CONNECT: hr = E_DWNLD_CANT_CONNECT; break;
case api_downloadManager::TICK_WRITE_ERROR: hr = E_DWNLD_WRITE_ERROR; break;
default: hr = E_DWNLD_BUSY; break;
}
}
if (NULL != ppszPath)
{
if (SUCCEEDED(hr))
*ppszPath = manager->GetLocation(cookie);
else
*ppszPath = NULL;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginDownloadResult::GetWaitHandle(HANDLE *handle)
{
if (NULL == handle)
return E_POINTER;
HRESULT hr = S_OK;
EnterCriticalSection(&lock);
if (NULL == completed)
{
completed = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == completed)
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
}
if (SUCCEEDED(hr) && FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginDownloadResult::GetData(void **data)
{
if (NULL == data)
return E_POINTER;
EnterCriticalSection(&lock);
*data = this->data;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginDownloadResult::RequestAbort(BOOL fDrop)
{
EnterCriticalSection(&lock);
if (FALSE != fDrop)
{
data = NULL;
callback = NULL;
}
if (0 != cookie && NULL != manager && 0 == (flagUserAbort & flags))
{
manager->CancelDownload(cookie);
SetState(stateAborting);
SetFlags(flagUserAbort, flagUserAbort);
}
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginDownloadResult::GetUrl(LPSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
HRESULT hr;
EnterCriticalSection(&lock);
if(NULL == manager || 0 == cookie)
hr = E_UNEXPECTED;
else
{
api_httpreceiver *receiver = manager->GetReceiver(cookie);
if (NULL == receiver) hr = E_FAIL;
else
{
LPCSTR url = receiver->get_url();
hr = StringCchCopyExA(pszBuffer, cchBufferMax, url, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
}
LeaveCriticalSection(&lock);
return hr;
}
void LoginDownloadResult::SetStatus()
{
EnterCriticalSection(&lock);
if (NULL != status && ((UINT)-1 == statusCookie))
{
LPCWSTR pszStatus;
switch(typeMask & flags)
{
case typeProviderList: pszStatus = MAKEINTRESOURCE(IDS_STATUS_UPDATEBEGIN); break;
default: pszStatus = NULL; break;
}
if (NULL != pszStatus)
{
BSTR bstrText;
if (FALSE == IS_INTRESOURCE(pszStatus))
bstrText = SysAllocString(pszStatus);
else
{
WCHAR szBuffer[256] = {0};
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)pszStatus, szBuffer, ARRAYSIZE(szBuffer));
bstrText = SysAllocString(szBuffer);
}
statusCookie = status->Add(bstrText);
if (((UINT)-1) == statusCookie)
SysFreeString(bstrText);
}
}
LeaveCriticalSection(&lock);
}
void LoginDownloadResult::RemoveStatus()
{
EnterCriticalSection(&lock);
if (NULL != status)
{
if (((UINT)-1) != statusCookie)
{
status->Remove(statusCookie);
statusCookie = (UINT)-1;
}
}
LeaveCriticalSection(&lock);
}
HRESULT LoginDownloadResult::CreateDownloadFileName(LPSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
HRESULT hr;
EnterCriticalSection(&lock);
if(NULL == manager || 0 == cookie)
hr = E_UNEXPECTED;
else
{
api_httpreceiver *receiver = manager->GetReceiver(cookie);
if (NULL == receiver) hr = E_FAIL;
else
{
LPCSTR url = receiver->get_url();
LPCSTR contentDisposition = receiver->getheader("content-disposition");
LPCSTR contentType = receiver->getheader("content-type");
hr = S_OK;
}
}
LeaveCriticalSection(&lock);
return hr;
}
void LoginDownloadResult::DownloadCompleted(int errorCode)
{
EnterCriticalSection(&lock);
result = errorCode;
SetState(stateCompleted);
HANDLE hEvent = completed;
Callback cb = callback;
LeaveCriticalSection(&lock);
if (NULL != hEvent)
SetEvent(hEvent);
if (NULL != cb)
cb(this, data);
RemoveStatus();
Release();
}
void LoginDownloadResult::Event_DownloadInit(DownloadToken token)
{
EnterCriticalSection(&lock);
AddRef();
cookie = token;
SetState(stateConnecting);
if (NULL != manager)
{
manager->RetainDownload(cookie);
if (typeProviderList == (typeMask & flags))
{
api_httpreceiver *receiver = manager->GetReceiver(token);
if (NULL != receiver)
receiver->AllowCompression();
}
}
LeaveCriticalSection(&lock);
SetStatus();
}
void LoginDownloadResult::Event_DownloadConnect(DownloadToken token)
{
EnterCriticalSection(&lock);
SetState(stateReceiving);
LeaveCriticalSection(&lock);
}
void LoginDownloadResult::Event_DownloadTick(DownloadToken token)
{
EnterCriticalSection(&lock);
if (stateConnecting == (stateMask & flags))
SetState(stateReceiving);
LeaveCriticalSection(&lock);
}
void LoginDownloadResult::Event_DownloadFinish(DownloadToken token)
{
DownloadCompleted(api_downloadManager::TICK_SUCCESS);
}
void LoginDownloadResult::Event_DownloadError(DownloadToken token, int errorCode)
{
DownloadCompleted(errorCode);
}
void LoginDownloadResult::Event_DownloadCancel(DownloadToken token)
{
DownloadCompleted(api_downloadManager::TICK_NODATA);
}
#define CBCLASS LoginDownloadResult
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONINIT, Event_DownloadInit)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONCONNECT, Event_DownloadConnect)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONFINISH, Event_DownloadFinish)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONERROR, Event_DownloadError)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONCANCEL, Event_DownloadCancel)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONTICK, Event_DownloadTick)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,110 @@
#ifndef NULLSOFT_AUTH_LOGIN_DOWNLOAD_RESULT_HEADER
#define NULLSOFT_AUTH_LOGIN_DOWNLOAD_RESULT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../dlmgr/api_downloadmanager.h"
#define E_DWNLD_OK S_OK
#define E_DWNLD_BUSY E_PENDING
#define E_DWNLD_FAIL E_FAIL
#define E_DWNLD_ABORT E_ABORT
#define E_DWNLD_TIMEOUT HRESULT_FROM_WIN32(ERROR_TIMEOUT)
#define E_DWNLD_CANT_CONNECT HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED)
#define E_DWNLD_WRITE_ERROR HRESULT_FROM_WIN32(ERROR_WRITE_FAULT)
class LoginStatus;
class LoginDownloadResult : public ifc_downloadManagerCallback
{
public:
typedef void (CALLBACK *Callback)(LoginDownloadResult *result, void *data);
typedef enum
{
stateMask = 0x00000FF00,
stateReady = 0x00000000,
stateInitializing = 0x00000100,
stateConnecting = 0x00000200,
stateReceiving = 0x00000300,
stateCompleted = 0x00000400,
stateAborting = 0x00000500,
} States;
typedef enum
{
typeMask = 0x0000000FF,
typeUnknown = 0x00000000,
typeImage = 0x00000001,
typeProviderList = 0x00000002,
} Types;
typedef enum
{
flagsMask = 0xFFFF0000,
flagUserAbort = 0x00010000,
} Flags;
protected:
LoginDownloadResult(api_downloadManager *pManager, UINT uType, Callback fnCallback, void *pData, LoginStatus *pStatus);
~LoginDownloadResult();
public:
static HRESULT CreateInstance(api_downloadManager *pManager, UINT uType, Callback fnCallback, void *pData, LoginStatus *pStatus, LoginDownloadResult **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
HRESULT GetWaitHandle(HANDLE *handle);
HRESULT GetData(void **data);
HRESULT GetType(UINT *type);
HRESULT GetState(UINT *state);
HRESULT GetFile(LPCWSTR *ppszPath);
HRESULT CreateDownloadFileName(LPSTR pszBuffer, UINT cchBufferMax);
HRESULT GetUrl(LPSTR pszBuffer, UINT cchBufferMax);
HRESULT RequestAbort(BOOL fDrop);
protected:
/* ifc_downloadManagerCallback */
void Event_DownloadFinish(DownloadToken token);
void Event_DownloadTick(DownloadToken token);
void Event_DownloadError(DownloadToken token, int errorCode);
void Event_DownloadCancel(DownloadToken token);
void Event_DownloadConnect(DownloadToken token);
void Event_DownloadInit(DownloadToken token);
void DownloadCompleted(int errorCode);
void SetState(UINT uState);
void SetType(UINT uType);
void SetFlags(UINT uFlags, UINT uMask);
void SetStatus();
void RemoveStatus();
protected:
size_t ref;
UINT flags;
LPWSTR address;
INT result;
api_downloadManager *manager;
DownloadToken cookie;
HANDLE completed;
Callback callback;
void *data;
LoginStatus *status;
UINT statusCookie;
CRITICAL_SECTION lock;
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGINDOWNLOADER_HEADER

View File

@@ -0,0 +1,269 @@
#include "./editboxExtender.h"
#include "./common.h"
#include <commctrl.h>
#define NAEF_USERFLAGSMASK 0x00FFFFFF
#define NAEF_UNICODE 0x01000000
typedef struct __EDITBOXEXTENDER
{
WNDPROC originalProc;
UINT flags;
DWORD dblclkTime;
LPWSTR rollbackText;
} EDITBOXEXTENDER;
#define EDITBOXEXTENDER_PROP L"NullsoftEditboxExtender"
#define GetEditbox(__hwnd) ((EDITBOXEXTENDER*)GetProp((__hwnd), EDITBOXEXTENDER_PROP))
static LRESULT CALLBACK EditboxExtender_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL EditboxExtender_AttachWindow(HWND hEditbox)
{
if (!IsWindow(hEditbox))
return FALSE;
EDITBOXEXTENDER *editbox = (EDITBOXEXTENDER*)GetProp(hEditbox, EDITBOXEXTENDER_PROP);
if (NULL != editbox) return TRUE;
editbox = (EDITBOXEXTENDER*)calloc(1, sizeof(EDITBOXEXTENDER));
if (NULL == editbox) return FALSE;
if (IsWindowUnicode(hEditbox))
editbox->flags |= NAEF_UNICODE;
editbox->originalProc = (WNDPROC)(LONG_PTR)((0 != (NAEF_UNICODE & editbox->flags)) ?
SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditboxExtender_WindowProc) :
SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditboxExtender_WindowProc));
if (NULL == editbox->originalProc || !SetProp(hEditbox, EDITBOXEXTENDER_PROP, editbox))
{
if (NULL != editbox->originalProc)
{
if (0 != (NAEF_UNICODE & editbox->flags))
SetWindowLongPtrW(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
else
SetWindowLongPtrA(hEditbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
}
free(editbox);
return FALSE;
}
return TRUE;
}
static void EditboxExtender_Detach(HWND hwnd)
{
EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
RemoveProp(hwnd, EDITBOXEXTENDER_PROP);
if (NULL == editbox)
return;
if (NULL != editbox->originalProc)
{
if (0 != (NAEF_UNICODE & editbox->flags))
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
else
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)editbox->originalProc);
}
free(editbox);
}
static LRESULT EditboxExtender_CallOrigWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
if (NULL == editbox || NULL == editbox->originalProc)
{
return (0 != (NAEF_UNICODE & editbox->flags)) ?
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
return (0 != (NAEF_UNICODE & editbox->flags)) ?
CallWindowProcW(editbox->originalProc, hwnd, uMsg, wParam, lParam) :
CallWindowProcA(editbox->originalProc, hwnd, uMsg, wParam, lParam);
}
static void EditboxExtender_OnDestroy(HWND hwnd)
{
EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
WNDPROC originalProc = editbox->originalProc;
BOOL fUnicode = (0 != (NAEF_UNICODE & editbox->flags));
EditboxExtender_Detach(hwnd);
if (NULL != originalProc)
{
if (FALSE != fUnicode)
CallWindowProcW(originalProc, hwnd, WM_DESTROY, 0, 0L);
else
CallWindowProcA(originalProc, hwnd, WM_DESTROY, 0, 0L);
}
}
static LRESULT EditboxExtender_OnGetDlgCode(HWND hwnd, INT vKey, MSG* pMsg)
{
LRESULT result = EditboxExtender_CallOrigWindowProc(hwnd, WM_GETDLGCODE, (WPARAM)vKey, (LPARAM)pMsg);
return result;
}
static void EditboxExtender_OnLButtonDown(HWND hwnd, UINT vKey, POINTS pts)
{
EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
if (NULL != editbox)
{
DWORD clickTime = GetTickCount();
if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + GetDoubleClickTime()))
{
SendMessage(hwnd, EM_SETSEL, 0, -1);
return;
}
}
EditboxExtender_CallOrigWindowProc(hwnd, WM_LBUTTONDOWN, (WPARAM)vKey, *((LPARAM*)&pts));
}
static void EditboxExtender_OnLButtonDblClk(HWND hwnd, UINT vKey, POINTS pts)
{
EDITBOXEXTENDER *editbox = GetEditbox(hwnd);
if (NULL == editbox) return;
DWORD clickTime = GetTickCount();
if (clickTime >= editbox->dblclkTime && clickTime <= (editbox->dblclkTime + 2*GetDoubleClickTime()))
{
INT r = (INT)SendMessage(hwnd, EM_CHARFROMPOS, 0, *(LPARAM*)&pts);
r = LOWORD(r);
SendMessage(hwnd, EM_SETSEL, (WPARAM)r, (LPARAM)r);
editbox->dblclkTime = 0;
}
else
{
editbox->dblclkTime = clickTime;
}
INT f, l;
SendMessage(hwnd, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
if (f != l) return;
EditboxExtender_CallOrigWindowProc(hwnd, WM_LBUTTONDBLCLK, (WPARAM)vKey, *((LPARAM*)&pts));
}
static void EditboxExtender_OnChar(HWND hwnd, UINT vKey, UINT state)
{
if (0 == (0x8000 & GetAsyncKeyState(VK_CONTROL)) && 0 == (0x8000 & GetAsyncKeyState(VK_MENU)))
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent)
{
NMCHAR nmh;
nmh.hdr.hwndFrom = hwnd;
nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
nmh.hdr.code = NM_CHAR;
nmh.ch = vKey;
nmh.dwItemNext = 0;
nmh.dwItemPrev = 0;
if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
return;
}
}
EditboxExtender_CallOrigWindowProc(hwnd, WM_CHAR, (WPARAM)vKey, (LPARAM)state);
}
static void EditboxExtender_OnKeyDown(HWND hwnd, UINT vKey, UINT state)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent)
{
NMKEY nmh;
nmh.hdr.hwndFrom = hwnd;
nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
nmh.hdr.code = NM_KEYDOWN;
nmh.nVKey = vKey;
nmh.uFlags = HIWORD(state);
if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
return;
}
EditboxExtender_CallOrigWindowProc(hwnd, WM_KEYDOWN, (WPARAM)vKey, (LPARAM)state);
}
static void EditboxExtender_PasteText(HWND hwnd, LPCWSTR pszClipboard)
{
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if (NULL != hParent)
{
EENMPASTE nmh;
nmh.hdr.hwndFrom = hwnd;
nmh.hdr.idFrom = (INT)(INT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
nmh.hdr.code = EENM_PASTE;
nmh.text = pszClipboard;
if (FALSE != (BOOL)SendMessage(hParent, WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
return;
}
SendMessage(hwnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)pszClipboard);
}
static void EditboxExtender_OnPaste(HWND hwnd)
{
IDataObject *pObject;
HRESULT hr = OleGetClipboard(&pObject);
if (SUCCEEDED(hr))
{
FORMATETC fmt = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stgm;
hr = pObject->GetData(&fmt, &stgm);
if(S_OK == hr)
{
LPCWSTR pClipboard = (LPCWSTR)GlobalLock(stgm.hGlobal);
EditboxExtender_PasteText(hwnd, pClipboard);
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
else
{
fmt.cfFormat = CF_TEXT;
hr = pObject->GetData(&fmt, &stgm);
if(S_OK == hr)
{
LPCSTR pClipboardAnsi = (LPCSTR)GlobalLock(stgm.hGlobal);
LPWSTR pClipboard;
if (FAILED(LoginBox_MultiByteToWideChar(CP_ACP, 0, pClipboardAnsi, -1, &pClipboard)))
pClipboard = NULL;
EditboxExtender_PasteText(hwnd, pClipboard);
LoginBox_FreeString(pClipboard);
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
}
pObject->Release();
}
}
static LRESULT CALLBACK EditboxExtender_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY: EditboxExtender_OnDestroy(hwnd); return 0;
case WM_GETDLGCODE: return EditboxExtender_OnGetDlgCode(hwnd, (INT)wParam, (MSG*)lParam);
case WM_LBUTTONDOWN: EditboxExtender_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_LBUTTONDBLCLK: EditboxExtender_OnLButtonDblClk(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); return 0;
case WM_CHAR: EditboxExtender_OnChar(hwnd, (UINT)wParam, (UINT)lParam); return 0;
case WM_KEYDOWN: EditboxExtender_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam); return 0;
case WM_PASTE: EditboxExtender_OnPaste(hwnd); return 1;
}
return EditboxExtender_CallOrigWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,22 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_EDITBOX_EXTENDER_HEADER
#define NULLSOFT_AUTH_LOGINBOX_EDITBOX_EXTENDER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
BOOL EditboxExtender_AttachWindow(HWND hEditbox);
// notification
typedef struct __EENMPASTE
{
NMHDR hdr;
LPCWSTR text;
}EENMPASTE;
#define EENM_FIRST 10
#define EENM_PASTE (EENM_FIRST + 0L)
#endif // NULLSOFT_AUTH_LOGINBOX_EDITBOX_EXTENDER_HEADER

View File

@@ -0,0 +1,401 @@
#include "./externalMngr.h"
#include "./common.h"
#include "../../winamp/jsapi.h"
ExternalManager::ExternalManager()
: ref(1), lastDispId(0)
{
InitializeCriticalSection(&lock);
}
ExternalManager::~ExternalManager()
{
EnterCriticalSection(&lock);
size_t index= list.size();
while(index--)
{
if (NULL != list[index].object)
list[index].object->Release();
}
LeaveCriticalSection(&lock);
DeleteCriticalSection(&lock);
}
HRESULT ExternalManager::CreateInstance(ExternalManager **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new ExternalManager();
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
STDMETHODIMP_(ULONG) ExternalManager::AddRef(void)
{
return InterlockedIncrement((LONG*)&ref);
}
STDMETHODIMP_(ULONG) ExternalManager::Release(void)
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
STDMETHODIMP ExternalManager::QueryInterface(REFIID riid, PVOID *ppvObject)
{
if (NULL == ppvObject)
return E_POINTER;
if (IsEqualIID(riid, IID_IDispatchEx))
*ppvObject = static_cast<IDispatchEx*>(this);
else if (IsEqualIID(riid, IID_IDispatch))
*ppvObject = static_cast<IDispatch*>(this);
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = static_cast<IUnknown*>(this);
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
if (NULL == *ppvObject)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
STDMETHODIMP ExternalManager::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
EnterCriticalSection(&lock);
UINT unknowns = 0;
size_t count = list.size();
for (UINT i = 0; i != cNames ; i++)
{
rgdispid[i] = DISPID_UNKNOWN;
for (size_t j =0; j < count; j++)
{
if (CSTR_EQUAL == CompareString(lcid, 0, rgszNames[i], -1, list[j].name, -1))
{
if (NULL != list[j].object)
rgdispid[i] = list[j].id;
else
unknowns++;
break;
}
if (DISPID_UNKNOWN == rgdispid[i])
unknowns++;
}
}
LeaveCriticalSection(&lock);
return (0 != unknowns) ? DISP_E_UNKNOWNNAME : S_OK;
}
STDMETHODIMP ExternalManager::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
return E_NOTIMPL;
}
STDMETHODIMP ExternalManager::GetTypeInfoCount(unsigned int FAR * pctinfo)
{
return E_NOTIMPL;
}
STDMETHODIMP ExternalManager::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
{
return InvokeEx(dispid, lcid, wFlags, pdispparams, pvarResult, pexecinfo, 0);
}
STDMETHODIMP ExternalManager::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
{
if (NULL == pid) return E_POINTER;
*pid = DISPID_UNKNOWN;
HRESULT hr = DISP_E_UNKNOWNNAME;
if (NULL != bstrName && L'\0' != *bstrName)
{
UINT compareFlags = 0;
if (0 != (fdexNameCaseInsensitive & grfdex))
compareFlags |= NORM_IGNORECASE;
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, compareFlags, bstrName, -1, list[index].name, -1))
{
if (NULL != list[index].object)
{
*pid = list[index].id;
hr = S_OK;
}
break;
}
}
LeaveCriticalSection(&lock);
}
return hr;
}
STDMETHODIMP ExternalManager::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
if (DISPATCH_METHOD == wFlags || DISPATCH_PROPERTYGET == wFlags || DISPATCH_CONSTRUCT == wFlags)
JSAPI_INIT_RESULT(pvarRes, VT_DISPATCH);
HRESULT hr(DISP_E_MEMBERNOTFOUND);
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (id == list[index].id)
{
if (NULL != list[index].object)
{
if (NULL != pvarRes &&
(DISPATCH_METHOD == wFlags || DISPATCH_PROPERTYGET == wFlags || DISPATCH_CONSTRUCT == wFlags))
{
list[index].object->AddRef();
pvarRes->pdispVal = list[index].object;
}
hr = S_OK;
}
break;
}
}
LeaveCriticalSection(&lock);
return hr;
}
STDMETHODIMP ExternalManager::DeleteMemberByName(BSTR bstrName, DWORD grfdex)
{
HRESULT hr = S_FALSE;
if (NULL != bstrName && L'\0' != *bstrName)
{
UINT compareFlags = 0;
if (0 != (fdexNameCaseInsensitive & grfdex))
compareFlags |= NORM_IGNORECASE;
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, compareFlags, bstrName, -1, list[index].name, -1))
{
if (NULL != list[index].object)
{
list[index].object->Release();
list[index].object = NULL;
hr = S_OK;
}
break;
}
}
LeaveCriticalSection(&lock);
}
return hr;
}
STDMETHODIMP ExternalManager::DeleteMemberByDispID(DISPID id)
{
HRESULT hr = S_FALSE;
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (id == list[index].id)
{
if (NULL != list[index].object)
{
list[index].object->Release();
list[index].object = NULL;
hr = S_OK;
}
break;
}
}
LeaveCriticalSection(&lock);
return hr;
}
STDMETHODIMP ExternalManager::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{
HRESULT hr(DISP_E_UNKNOWNNAME);
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (id == list[index].id)
{
if (NULL != list[index].object)
{
if (NULL != pgrfdex)
{
*pgrfdex = 0;
if (0 != (grfdexPropCanAll & grfdexFetch))
*pgrfdex |= (fdexPropCanGet | fdexPropCanCall);
if (0 != (grfdexPropCannotAll & grfdexFetch))
*pgrfdex |= (fdexPropCannotPut | fdexPropCanPutRef | fdexPropCannotConstruct | fdexPropCannotSourceEvents);
if (0 != (grfdexPropExtraAll & grfdexFetch))
*pgrfdex |= (fdexPropNoSideEffects | fdexPropNoSideEffects);
}
hr = S_OK;
}
break;
}
}
LeaveCriticalSection(&lock);
return hr;
}
STDMETHODIMP ExternalManager::GetMemberName(DISPID id, BSTR *pbstrName)
{
HRESULT hr(DISP_E_UNKNOWNNAME);
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (id == list[index].id)
{
if (NULL != list[index].object)
{
if (NULL != pbstrName)
{
*pbstrName = SysAllocString(list[index].name);
hr = S_OK;
}
}
break;
}
}
LeaveCriticalSection(&lock);
return hr;
}
STDMETHODIMP ExternalManager::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
{
HRESULT hr(S_FALSE);
if (NULL == pid) return S_FALSE;
*pid = DISPID_UNKNOWN;
EnterCriticalSection(&lock);
size_t count = list.size();
if (DISPID_STARTENUM == id)
{
if (count > 0)
{
*pid = list[0].id;
hr = S_OK;
}
}
else
{
for(size_t i = 0; i < count; i++)
{
if (id == list[i].id)
{
i++;
if (i < count)
{
*pid = list[i].id;
hr = S_OK;
}
break;
}
}
}
LeaveCriticalSection(&lock);
return hr;
}
STDMETHODIMP ExternalManager::GetNameSpaceParent(IUnknown **ppunk)
{
return E_NOTIMPL;
}
HRESULT ExternalManager::AddDispatch(LPCWSTR pszName, IDispatch *pDispatch, DISPID *pid)
{
if (NULL != pid)
*pid = DISPID_UNKNOWN;
if (NULL == pszName || L'\0' == pszName || NULL == pDispatch)
return E_INVALIDARG;
HRESULT hr;
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, pszName, -1, list[index].name, -1))
{
if (NULL != list[index].object)
{
hr = E_FAIL;
}
else
{
list[index].object = pDispatch;
pDispatch->AddRef();
*pid = list[index].id;
hr = S_OK;
}
break;
}
}
if ((size_t)-1 == index)
{
DispatchRecord r;
r.name = LoginBox_CopyString(pszName);
if (NULL == r.name)
hr = E_OUTOFMEMORY;
else
{
r.id = ++lastDispId;
r.object = pDispatch;
pDispatch->AddRef();
list.push_back(r);
*pid = r.id;
hr = S_OK;
}
}
LeaveCriticalSection(&lock);
return hr;
}

View File

@@ -0,0 +1,65 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_EXTERNAL_MANAGER_HEADER
#define NULLSOFT_AUTH_LOGINBOX_EXTERNAL_MANAGER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <dispex.h>
#include "../nu/Vectors.h"
class ExternalManager : public IDispatchEx
{
protected:
ExternalManager();
~ExternalManager();
public:
static HRESULT CreateInstance(ExternalManager **instance);
public:
/* IUnknown */
STDMETHOD(QueryInterface)(REFIID riid, PVOID *ppvObject);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
/* IDispatch*/
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid);
STDMETHOD(GetTypeInfo)(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo);
STDMETHOD(GetTypeInfoCount)(unsigned int FAR * pctinfo);
STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr);
/* IDispatchEx*/
STDMETHOD (GetDispID)(BSTR bstrName, DWORD grfdex, DISPID *pid);
STDMETHOD (InvokeEx)(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller);
STDMETHOD (DeleteMemberByName)(BSTR bstrName, DWORD grfdex);
STDMETHOD (DeleteMemberByDispID)(DISPID id);
STDMETHOD (GetMemberProperties)(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex);
STDMETHOD (GetMemberName)(DISPID id, BSTR *pbstrName);
STDMETHOD (GetNextDispID)(DWORD grfdex, DISPID id, DISPID *pid);
STDMETHOD (GetNameSpaceParent)(IUnknown **ppunk);
public:
HRESULT AddDispatch(LPCWSTR pszName, IDispatch *pDispatch, DISPID *pid);
protected:
typedef struct __DispatchRecord
{
DISPID id;
LPWSTR name;
IDispatch *object;
} DispatchRecord;
typedef Vector<DispatchRecord> DispatchList;
protected:
ULONG ref;
DispatchList list;
CRITICAL_SECTION lock;
DISPID lastDispId;
};
#endif //NULLSOFT_AUTH_LOGINBOX_EXTERNAL_MANAGER_HEADER

View File

@@ -0,0 +1,434 @@
#include "./graphics.h"
#include "./shlwapi.h"
BOOL Image_ColorOverEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, BOOL premult, COLORREF rgb)
{
LONG pitch;
UINT a, r, g, b, ma, mr, mg, mb;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (step < 3)
return TRUE;
if (cy < 0) cy -= cy;
a = (LOBYTE((rgb)>>24)); r = GetRValue(rgb); g = GetGValue(rgb); b = GetBValue(rgb);
ma = 255 - a; mr = r * 255; mg = g * 255; mb = b * 255;
if (0 == a)
return TRUE;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
if (0xFF == a)
{
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
cursor[0] = (BYTE)b;
cursor[1] = (BYTE)g;
cursor[2] = (BYTE)r;
// cursor[3] = 0xFF;
}
}
return TRUE;
}
if (premult)
{
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
UINT t = (mb + ma * cursor[0] + 127) / 255;
cursor[0] = (t > 0xFF) ? 0xFF : t;
t = (mg + ma * cursor[1] + 127) / 255;
cursor[1] = (t > 0xFF) ? 0xFF : t;
t = (mr+ ma * cursor[2] + 127) / 255;
cursor[2] = (t > 0xFF) ? 0xFF : t;
}
}
}
else
{
WORD k = (((255 - a)*255 + 127)/255);
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
cursor[0] = (b*a + k*cursor[0] + 127)/255;
cursor[1] = (g*a + k*cursor[1] + 127)/255;
cursor[2] = (r*a + k*cursor[2] + 127)/255;
// cursor[3] = (a*a + k*cursor[3] + 127)/255;
}
}
}
return TRUE;
}
BOOL Image_ColorizeEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, BOOL premult, COLORREF rgbBottom, COLORREF rgbTop)
{
LONG pitch;
UINT rBottom, gBottom, bBottom;
UINT rTop, gTop, bTop;
INT step = (bpp>>3);
LPBYTE startLine, line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (cy < 0)
cy = -cy;
rBottom = GetRValue(rgbBottom);
gBottom = GetGValue(rgbBottom);
bBottom = GetBValue(rgbBottom);
rTop = GetRValue(rgbTop);
gTop = GetGValue(rgbTop);
bTop = GetBValue(rgbTop);
UINT a, k;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
startLine = pPixels + pitch * ofs + x*step;
line = startLine;
for (y = cy; y-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
a = (255- cursor[2]);
if (a < 0) a = 0;
if (a > 254)
{
cursor[0] = bTop;
cursor[1] = gTop;
cursor[2] = rTop;
}
else if (a== 0)
{
cursor[0] = bBottom;
cursor[1] = gBottom;
cursor[2] = rBottom;
}
else
{
k = (((255 - a)*255 + 127)/255);
cursor[0] = (bTop * a + k*bBottom + 127)/255;
cursor[1] = (gTop * a + k*gBottom + 127)/255;
cursor[2] = (rTop * a + k*rBottom + 127)/255;
}
}
}
if (32 == bpp && FALSE != premult)
{
line = startLine;
for (y = cy; y-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
a = cursor[3];
k = MulDiv(cursor[0], a, 255);
cursor[0] = (k < 255) ? k : 255;
k = MulDiv(cursor[1], a, 255);
cursor[1] = (k < 255) ? k : 255;
k = MulDiv(cursor[2], a, 255);
cursor[2] = (k < 255) ? k : 255;
}
}
}
return TRUE;
}
BOOL Image_PremultiplyEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
UINT a,k;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
a = cursor[3];
if (0 == a)
{
cursor[0] = 0;
cursor[1] = 0;
cursor[2] = 0;
}
else if (255 != a)
{
k = MulDiv((UINT)cursor[0], a, 255);
cursor[0] = (k < 255) ? k : 255;
k = MulDiv((UINT)cursor[1], a, 255);
cursor[1] = (k < 255) ? k : 255;
k = MulDiv((UINT)cursor[2], a, 255);
cursor[2] = (k < 255) ? k : 255;
}
}
}
return TRUE;
}
BOOL Image_SaturateEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT n, BOOL fScale)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (FALSE == fScale)
{
if (n < 0) n = 0;
else if (n > 1000) n = 1000;
}
else
{
if (n < -1000) n = -1000;
else if (n > 1000) n = 1000;
}
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
COLORREF rgb;
INT k;
WORD h, l, s;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
rgb = RGB(cursor[2], cursor[1], cursor[0]);
ColorRGBToHLS(rgb, &h, &l, &s);
if(FALSE == fScale)
s = ((WORD)((240 * n)/1000));
else
{
k = s;
s = (WORD)(k + (k * n) /1000);
}
rgb = ColorHLSToRGB(h, l, s);
cursor[0] = GetBValue(rgb);
cursor[1] = GetGValue(rgb);
cursor[2] = GetRValue(rgb);
}
}
return TRUE;
}
BOOL Image_AdjustAlphaEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT n, BOOL fScale)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (FALSE == fScale)
{
if (n < 0) n = 0;
else if (n > 1000) n = 1000;
}
else
{
if (n < -1000) n = -1000;
else if (n > 1000) n = 1000;
}
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
INT k;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
if(FALSE == fScale)
cursor[3] = ((BYTE)((255 * n)/1000));
else
{
k = cursor[3];
k = k + MulDiv(k, n, 1000);
if (k > 255) k = 255;
cursor[3] = (BYTE)k;
}
}
}
return TRUE;
}
BOOL Image_AdjustSaturationAlphaEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT nSaturation, INT nAlpha)
{
if (32 != bpp)
return FALSE;
LONG pitch;
INT step = (bpp>>3);
LPBYTE line, cursor;
pitch = bitmapCX * step;
while (pitch%4) pitch++;
if (nSaturation < -1000) nSaturation = -1000;
else if (nSaturation > 1000) nSaturation = 1000;
if (nAlpha < -1000) nAlpha = -1000;
else if (nAlpha > 1000) nAlpha = 1000;
if (cy < 0)
cy = -cy;
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
line = pPixels + pitch * ofs + x*step;
INT k;
COLORREF rgb;
WORD h, l, s;
for (; cy-- != 0; line += pitch)
{
for (x = cx, cursor = line; x-- != 0; cursor += step)
{
k = cursor[3];
k = k + MulDiv(k, nAlpha, 1000);
if (k > 255) k = 255;
cursor[3] = (BYTE)k;
rgb = RGB(cursor[2], cursor[1], cursor[0]);
ColorRGBToHLS(rgb, &h, &l, &s);
k = s;
k = k + MulDiv(k, nSaturation, 1000);
if (k > 240) k = 240;
s = (WORD)k;
rgb = ColorHLSToRGB(h, l, s);
cursor[0] = GetBValue(rgb);
cursor[1] = GetGValue(rgb);
cursor[2] = GetRValue(rgb);
}
}
return TRUE;
}
BOOL Image_ColorOver(HBITMAP hbmp, RECT *prcPart, BOOL premult, COLORREF rgb)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_ColorOverEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, premult, rgb);
}
BOOL Image_Premultiply(HBITMAP hbmp, RECT *prcPart)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel);
}
BOOL Image_Saturate(HBITMAP hbmp, RECT *prcPart, INT n, BOOL fScale)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_SaturateEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, n, fScale);
}
BOOL Image_AdjustAlpha(HBITMAP hbmp, RECT *prcPart, INT n, BOOL fScale)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_AdjustAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, n, fScale);
}
BOOL Image_AdjustSaturationAlpha(HBITMAP hbmp, RECT *prcPart, INT nSaturation, INT nAlpha)
{
DIBSECTION dibsec;
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
return FALSE;
return Image_AdjustSaturationAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
prcPart->left, prcPart->top,
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
dibsec.dsBm.bmBitsPixel, nSaturation, nAlpha);
}
COLORREF Color_Blend(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
{
if (alpha > 254) return rgbTop;
if (alpha < 0) return rgbBottom;
WORD k = (((255 - alpha)*255 + 127)/255);
return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
(GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
(GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
}

View File

@@ -0,0 +1,29 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_GRAPHICS_HEADER
#define NULLSOFT_AUTH_LOGINBOX_GRAPHICS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
BOOL Image_ColorOver(HBITMAP hbmp, RECT *prcPart, BOOL premult, COLORREF rgb);
BOOL Image_ColorOverEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, BOOL premult, COLORREF rgb);
BOOL Image_ColorizeEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, BOOL premult, COLORREF rgbBottom, COLORREF rgbTop);
BOOL Image_Premultiply(HBITMAP hbmp, RECT *prcPart);
BOOL Image_PremultiplyEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp);
BOOL Image_Saturate(HBITMAP hbmp, RECT *prcPart, INT n, BOOL fScale);
BOOL Image_SaturateEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT n, BOOL fScale);
BOOL Image_AdjustAlpha(HBITMAP hbmp, RECT *prcPart, INT n, BOOL fScale);
BOOL Image_AdjustAlphaEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT n, BOOL fScale);
BOOL Image_AdjustSaturationAlpha(HBITMAP hbmp, RECT *prcPart, INT nSaturation, INT nAlpha);
BOOL Image_AdjustSaturationAlphaEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, INT nSaturation, INT nAlpha);
COLORREF Color_Blend(COLORREF rgbTop, COLORREF rgbBottom, INT alpha);
#endif //NULLSOFT_AUTH_LOGINBOX_GRAPHICS_HEADER

View File

@@ -0,0 +1,357 @@
#include "./imageCache.h"
#include "./imageLoader.h"
#include "./graphics.h"
#include "./loginBox.h"
#include <api/service/waservicefactory.h>
#include "../../ombrowser/ifc_omutility.h"
#include "../../ombrowser/ifc_omcachemanager.h"
#include "../../ombrowser/ifc_omcachegroup.h"
#include "../../ombrowser/ifc_omcacherecord.h"
#include "../api.h"
LoginImageCache::LoginImageCache(HWND hLoginbox)
: ref(1), hwnd(hLoginbox), group(NULL)
{
InitializeCriticalSection(&lock);
}
LoginImageCache::~LoginImageCache()
{
if (NULL != group)
{
group->Release();
}
DeleteCriticalSection(&lock);
}
HRESULT LoginImageCache::CreateInstance(HWND hLoginbox, LoginImageCache **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = NULL;
if (NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginImageCache(hLoginbox);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
size_t LoginImageCache::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t LoginImageCache::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int LoginImageCache::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_OmCacheCallback))
*object = static_cast<ifc_omcachecallback*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void LoginImageCache::PathChanged(ifc_omcacherecord *record)
{
HWND hLoginbox;
EnterCriticalSection(&lock);
hLoginbox = hwnd;
LeaveCriticalSection(&lock);
if (NULL != hLoginbox && FALSE != IsWindow(hLoginbox))
{
IMAGECACHERESULT result;
result.imageCache = this;
result.cacheRecord = record;
SendMessage(hLoginbox, NLBM_IMAGECACHED, 0, (LPARAM)&result);
}
}
void LoginImageCache::Finish()
{
EnterCriticalSection(&lock);
ifc_omcachegroup *groupCopy = group;
if (NULL != groupCopy)
groupCopy->AddRef();
LeaveCriticalSection(&lock);
if (NULL != groupCopy)
{
groupCopy->Clear();
WCHAR szGroup[64] = {0};
if (SUCCEEDED(groupCopy->GetName(szGroup, ARRAYSIZE(szGroup))))
{
waServiceFactory *serviceFactory = WASABI_API_SVC->service_getServiceByGuid(IFC_OmUtility);
if (NULL != serviceFactory)
{
ifc_omutility *omUtility = (ifc_omutility*)serviceFactory->getInterface();
if (NULL != omUtility)
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(omUtility->GetCacheManager(&cacheManager)))
{
cacheManager->Delete(szGroup);
cacheManager->Release();
}
omUtility->Release();
}
}
}
groupCopy->Release();
}
}
HRESULT LoginImageCache::InitGroup()
{
HRESULT hr;
EnterCriticalSection(&lock);
if (NULL != group)
{
hr = S_FALSE;
}
else
{
hr = S_OK;
waServiceFactory *serviceFactory = WASABI_API_SVC->service_getServiceByGuid(IFC_OmUtility);
if (NULL != serviceFactory)
{
ifc_omutility *omUtility = (ifc_omutility*)serviceFactory->getInterface();
if (NULL != omUtility)
{
ifc_omcachemanager *cacheManager;
if (SUCCEEDED(omUtility->GetCacheManager(&cacheManager)))
{
if (FAILED(cacheManager->Find(L"loginBox", TRUE, &group, NULL)))
group = NULL;
cacheManager->Release();
}
omUtility->Release();
}
}
if (NULL == group)
hr = E_NOINTERFACE;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginImageCache::GetImageListIndex(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled)
{
if (NULL == pszPath || L'\0' == *pszPath)
return E_INVALIDARG;
HRESULT hr;
WCHAR szBuffer[2048] = {0};
EnterCriticalSection(&lock);
BOOL fCreated = FALSE;
hr = InitGroup();
if (SUCCEEDED(hr))
{
ifc_omcacherecord *record;
hr = group->Find(pszPath, TRUE, &record, &fCreated);
if (S_OK != hr)
{
if (S_FALSE == hr)
hr = E_PENDING;
}
else
{
record->RegisterCallback(this);
hr = record->GetPath(szBuffer, ARRAYSIZE(szBuffer));
record->Release();
}
}
LeaveCriticalSection(&lock);
if (FAILED(hr))
return hr;
return GetImageListIndexLocal(szBuffer, himl, index, indexActive, indexDisabled);
}
HRESULT LoginImageCache::GetImageListIndexLocal(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled)
{
if (NULL == himl || NULL == pszPath || L'\0' == *pszPath)
return E_INVALIDARG;
if (NULL == index && NULL == indexActive && NULL == indexDisabled)
return E_INVALIDARG;
INT destWidth, destHeight;
if (0 == ImageList_GetIconSize(himl, &destWidth, &destHeight))
return E_FAIL;
INT imageWidth, imageHeight;
HBITMAP hbmp = ImageLoader_LoadBitmap(NULL, pszPath, FALSE, &imageWidth, &imageHeight);
if (NULL == hbmp)
return E_FAIL;
HRESULT hr = S_OK;
RECT imageRect;
SetRect(&imageRect, 0, 0, imageWidth, imageHeight);
if (NULL != indexActive)
{
*indexActive = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *indexActive) hr = E_FAIL;
}
if (NULL != index)
{
Image_AdjustSaturationAlpha(hbmp, &imageRect, -150, -100);
*index = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *index) hr = E_FAIL;
}
if (NULL != indexDisabled)
{
Image_AdjustSaturationAlpha(hbmp, &imageRect, -600, -600);
*indexDisabled = ImageList_Add(himl, hbmp, NULL);
if (((UINT)-1) == *indexDisabled) hr = E_FAIL;
}
if (NULL != hbmp)
DeleteObject(hbmp);
return hr;
}
HBITMAP LoginImageCache::AdjustBitmapSize(HBITMAP hBitmap, INT forceWidth, INT forceHeight)
{
BITMAP bm;
if (sizeof(BITMAP) != GetObject(hBitmap, sizeof(bm), &bm))
return NULL;
if (bm.bmHeight < 0) bm.bmHeight = -bm.bmHeight;
if (bm.bmWidth == forceWidth && bm.bmHeight == forceHeight)
return hBitmap;
HDC hdc, hdcSrc, hdcDst;
hdc = GetDCEx(NULL, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL == hdc) return NULL;
hdcSrc = CreateCompatibleDC(hdc);
hdcDst = CreateCompatibleDC(hdc);
BITMAPINFOHEADER bhi;
ZeroMemory(&bhi, sizeof(bhi));
bhi.biSize = sizeof(bhi);
bhi.biCompression = BI_RGB;
bhi.biBitCount = 32;
bhi.biPlanes = 1;
bhi.biWidth = forceWidth;
bhi.biHeight = -forceHeight;
UINT *pixelData;
HBITMAP hbmpDst = CreateDIBSection(NULL, (LPBITMAPINFO)&bhi, DIB_RGB_COLORS, (void**)&pixelData, NULL, 0);
if (NULL != hbmpDst)
{
for (INT i = 0; i < forceWidth * forceHeight; i++)
pixelData[i] = 0x00FFFFFF;
}
ReleaseDC(NULL, hdc);
if (NULL != hdcSrc && NULL != hdcDst && NULL != hbmpDst)
{
HBITMAP hbmpSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
HBITMAP hbmpDstOrig = (HBITMAP)SelectObject(hdcDst, hbmpDst);
BOOL result;
if (bm.bmWidth <= forceWidth && bm.bmHeight <= forceHeight)
{
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
result = GdiAlphaBlend(hdcDst, (forceWidth - bm.bmWidth)/2, (forceHeight - bm.bmHeight)/2,
bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, bf);
}
else
{
SetStretchBltMode(hdcDst, HALFTONE);
result = StretchBlt(hdcDst, 0, 0, forceWidth, forceHeight,
hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
}
if(FALSE != result)
{
hBitmap = hbmpDst;
hbmpDst = NULL;
}
else
hBitmap = NULL;
SelectObject(hdcSrc, hbmpSrcOrig);
SelectObject(hdcDst, hbmpDstOrig);
}
else
{
hBitmap = NULL;
}
if (NULL != hdcDst) DeleteDC(hdcDst);
if (NULL != hdcSrc) DeleteDC(hdcSrc);
if (NULL != hbmpDst) DeleteObject(hbmpDst);
return hBitmap;
}
#define CBCLASS LoginImageCache
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
VCB(API_PATHCHANGED, PathChanged)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,53 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_IMAGECACHE_HEADER
#define NULLSOFT_AUTH_LOGINBOX_IMAGECACHE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../ombrowser/ifc_omcachecallback.h"
#include <commctrl.h>
class ifc_omcachegroup;
class ifc_omcacherecord;
class LoginImageCache : public ifc_omcachecallback
{
protected:
LoginImageCache(HWND hLoginbox);
~LoginImageCache();
public:
static HRESULT CreateInstance(HWND hLoginbox, LoginImageCache **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_omcachecallback */
void PathChanged(ifc_omcacherecord *record);
void Finish();
HRESULT GetImageListIndex(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled);
HRESULT GetImageListIndexLocal(LPCWSTR pszPath, HIMAGELIST himl, UINT *index, UINT *indexActive, UINT *indexDisabled);
private:
HRESULT InitGroup();
HBITMAP AdjustBitmapSize(HBITMAP hBitmap, INT forceWidth, INT forceHeight);
protected:
size_t ref;
HWND hwnd;
ifc_omcachegroup *group;
CRITICAL_SECTION lock;
private:
RECVS_DISPATCH;
};
#endif // NULLSOFT_AUTH_LOGINBOX_IMAGECACHE_HEADER

View File

@@ -0,0 +1,331 @@
#include "./imageLoader.h"
#include "./common.h"
#include "../api.h"
#include <api/service/waservicefactory.h>
#include <shlwapi.h>
template <class api_T>
void ImageLoader_ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if (WASABI_API_SVC)
{
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
if (factory)
api_t = (api_T *)factory->getInterface();
}
}
typedef BOOL (CALLBACK *IMAGEDATAPROCESSOR)(const void * /*data*/, size_t /*dataSize*/, ULONG_PTR /*param*/);
typedef struct __LOADDATAPARAM
{
BOOL premultiply;
INT cx;
INT cy;
void *pixels;
} LOADDATAPARAM;
typedef struct __GETDIMENSIONPARAM
{
INT cx;
INT cy;
} GETDIMENSIONPARAM;
static BOOL CALLBACK ImageLoader_LoadDataCallback(const void *data, size_t size, ULONG_PTR param)
{
LOADDATAPARAM *loadParam = (LOADDATAPARAM*)param;
if (NULL == loadParam) return FALSE;
if (NULL == WASABI_API_PNGLOADER)
{
ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
if (NULL == WASABI_API_PNGLOADER)
return FALSE;
}
loadParam->pixels = (FALSE == loadParam->premultiply) ?
WASABI_API_PNGLOADER->loadImageData(data, (INT)size, &loadParam->cx, &loadParam->cy) :
WASABI_API_PNGLOADER->loadImage(data, (INT)size, &loadParam->cx, &loadParam->cy);
return (NULL != loadParam->pixels);
}
static BOOL CALLBACK ImageLoader_GetDimensionsCallback(const void *data, size_t size, ULONG_PTR param)
{
GETDIMENSIONPARAM *dimensionParam = (GETDIMENSIONPARAM*)param;
if (NULL == dimensionParam) return FALSE;
if (NULL == WASABI_API_PNGLOADER)
{
ImageLoader_ServiceBuild(WASABI_API_PNGLOADER, pngLoaderGUID);
if (NULL == WASABI_API_PNGLOADER)
return FALSE;
}
return WASABI_API_PNGLOADER->getDimensions(data, (INT)size, &dimensionParam->cx, &dimensionParam->cy);
}
static BOOL ImageLoader_ProcessResource(HINSTANCE hInstance, LPCWSTR pszName, LPCWSTR pszType, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
{
HRSRC res = FindResourceW(hInstance, pszName, pszType);
if (NULL == res) return FALSE;
BOOL fSucceeded = FALSE;
HANDLE handle = LoadResource(hInstance, res);
if (NULL != handle)
{
UINT resourceSize = SizeofResource(hInstance, res);
if (0 != resourceSize)
{
void *resourceData = LockResource(handle);
if (NULL != resourceData)
fSucceeded = processor(resourceData, resourceSize, param);
}
FreeResource(handle);
}
return fSucceeded;
}
static HRESULT ImageLoader_ParseResProtocol(LPWSTR pszAddress, LPCWSTR defaultType, HINSTANCE *module, LPCWSTR *resourceName, LPCWSTR *resourceType)
{
if (NULL == module || NULL == resourceName || NULL == resourceType)
return E_POINTER;
if (NULL == pszAddress || L'\0' == *pszAddress)
return E_INVALIDARG;
INT cchAddress = lstrlenW(pszAddress);
const WCHAR szPrefix[] = L"res://";
INT cchPrefix = ARRAYSIZE(szPrefix) - 1;
if (cchAddress <= cchPrefix)
return S_FALSE;
if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszAddress, cchPrefix, szPrefix, cchPrefix))
return S_FALSE;
pszAddress += cchPrefix;
cchAddress -= cchPrefix;
LPWSTR resType = NULL;
LPWSTR resName = NULL;
LPWSTR p = pszAddress + cchAddress;
while (p != pszAddress && L'/' != *p) p--;
if (p != pszAddress && p < (pszAddress + cchAddress))
{
resName = p + 1;
*p = L'\0';
p--;
}
if (NULL == resName || L'\0' == *resName)
return E_FAIL;
while (p != pszAddress && L'/' != *p) p--;
if (p != pszAddress && p < resName)
{
resType = p + 1;
if (L'\0' == *resType)
{
resType = NULL;
}
else
{
resType = p + 1;
*p = L'\0';
p--;
}
}
HINSTANCE hModule;
hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (NULL == hModule)
{
UINT errorCode = GetLastError();
if (NULL != resType)
{
*(resType - 1) = L'/';
resType = NULL;
hModule = LoadLibraryExW(pszAddress, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (NULL == hModule) errorCode = GetLastError();
}
if (ERROR_SUCCESS != errorCode)
return HRESULT_FROM_WIN32(errorCode);
}
if (NULL == resType)
resType = (LPWSTR)defaultType;
if (NULL != resType && FALSE == IS_INTRESOURCE(resType) && L'#' == *resType)
{
INT typeId;
if (FALSE != StrToIntExW(resType + 1, STIF_DEFAULT, &typeId))
resType = MAKEINTRESOURCEW(typeId);
}
if (NULL != resName && FALSE == IS_INTRESOURCE(resName) && L'#' == *resName)
{
INT nameId;
if (FALSE != StrToIntExW(resName + 1, STIF_DEFAULT, &nameId))
resName = MAKEINTRESOURCEW(nameId);
}
*module = hModule;
*resourceName = resName;
*resourceType = resType;
return S_OK;
}
static BOOL ImageLoader_ProcessFile(LPCWSTR pszPath, IMAGEDATAPROCESSOR processor, ULONG_PTR param)
{
HINSTANCE resModule;
LPCWSTR resName, resType;
BOOL fSucceeded = FALSE;
LPWSTR name = LoginBox_CopyString(pszPath);
HRESULT hr = ImageLoader_ParseResProtocol(name, RT_RCDATA, &resModule, &resName, &resType);
if (S_OK == hr)
{
fSucceeded = ImageLoader_ProcessResource(resModule, resName, resType, processor, param);
LoginBox_FreeString(name);
return fSucceeded;
}
LoginBox_FreeString(name);
if (FAILED(hr))
return FALSE;
HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile)
return FALSE;
UINT resourceSize = GetFileSize(hFile, NULL);
if (INVALID_FILE_SIZE != resourceSize)
{
void *resourceData = malloc(resourceSize);
if (NULL != resourceData)
{
DWORD readed = 0;
if (0 != ReadFile(hFile, resourceData, resourceSize, &readed, NULL) || resourceSize != readed)
fSucceeded = processor(resourceData, resourceSize, param);
free(resourceData);
}
}
CloseHandle(hFile);
return fSucceeded;
}
void *ImageLoader_LoadData(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
{
BOOL fSucceeded;
LOADDATAPARAM param;
param.premultiply = fPremultiply;
if (NULL == hInstance && !IS_INTRESOURCE(pszName))
fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
else
fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_LoadDataCallback, (ULONG_PTR)&param);
if (FALSE == fSucceeded)
{
if (NULL != widthOut) *widthOut = 0;
if (NULL != heightOut) *heightOut = 0;
return NULL;
}
if (NULL != widthOut) *widthOut = param.cx;
if (NULL != heightOut) *heightOut = param.cy;
return param.pixels;
}
void ImageLoader_FreeData(void *data)
{
if (NULL == data)
return;
if (NULL == WASABI_API_MEMMNGR)
{
ImageLoader_ServiceBuild(WASABI_API_MEMMNGR, memMgrApiServiceGuid);
if (NULL == WASABI_API_MEMMNGR) return;
}
WASABI_API_MEMMNGR->sysFree(data);
}
HBITMAP ImageLoader_LoadBitmapEx(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, BITMAPINFOHEADER *headerInfo, void **dataOut)
{
INT imageCX, imageCY;
void *data = ImageLoader_LoadData(hInstance, pszName, fPremultiply, &imageCX, &imageCY);
if (NULL == data) return NULL;
ZeroMemory(headerInfo, sizeof(BITMAPINFOHEADER));
headerInfo->biSize = sizeof(BITMAPINFOHEADER);
headerInfo->biCompression = BI_RGB;
headerInfo->biBitCount = 32;
headerInfo->biPlanes = 1;
headerInfo->biWidth = imageCX;
headerInfo->biHeight = -imageCY;
void *pixelData;
HBITMAP bitmap = CreateDIBSection(NULL, (LPBITMAPINFO)headerInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
if (NULL != bitmap)
{
if (NULL != dataOut) *dataOut = pixelData;
CopyMemory(pixelData, data, headerInfo->biWidth * abs(headerInfo->biHeight) * sizeof(DWORD));
}
else
{
if (NULL != dataOut) *dataOut = NULL;
}
ImageLoader_FreeData(data);
return bitmap;
}
HBITMAP ImageLoader_LoadBitmap(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut)
{
BITMAPINFOHEADER header;
HBITMAP bitmap = ImageLoader_LoadBitmapEx(hInstance, pszName, fPremultiply, &header, NULL);
if (NULL != bitmap)
{
if (NULL != widthOut) *widthOut = header.biWidth;
if (NULL != heightOut) *heightOut = header.biHeight;
}
else
{
if (NULL != widthOut) *widthOut = 0;
if (NULL != heightOut) *heightOut = 0;
}
return bitmap;
}
BOOL ImageLoader_GetDimensions(HINSTANCE hInstance, LPCWSTR pszName, INT *widthOut, INT *heightOut)
{
BOOL fSucceeded;
GETDIMENSIONPARAM param;
if (NULL == hInstance && !IS_INTRESOURCE(pszName))
fSucceeded = ImageLoader_ProcessFile(pszName, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
else
fSucceeded = ImageLoader_ProcessResource(hInstance, pszName, RT_RCDATA, ImageLoader_GetDimensionsCallback, (ULONG_PTR)&param);
if (FALSE == fSucceeded)
{
if (NULL != widthOut) *widthOut = 0;
if (NULL != heightOut) *heightOut = 0;
return FALSE;
}
if (NULL != widthOut) *widthOut = param.cx;
if (NULL != heightOut) *heightOut = param.cy;
return TRUE;
}

View File

@@ -0,0 +1,16 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_IMAGELOADER_HEADER
#define NULLSOFT_AUTH_LOGINBOX_IMAGELOADER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
void *ImageLoader_LoadData(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut);
void ImageLoader_FreeData(void *data);
HBITMAP ImageLoader_LoadBitmapEx(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, BITMAPINFOHEADER *headerInfo, void **dataOut);
HBITMAP ImageLoader_LoadBitmap(HINSTANCE hInstance, LPCWSTR pszName, BOOL fPremultiply, INT *widthOut, INT *heightOut);
BOOL ImageLoader_GetDimensions(HINSTANCE hInstance, LPCWSTR pszName, INT *widthOut, INT *heightOut);
#endif //NULLSOFT_AUTH_LOGINBOX_IMAGELOADER_HEADER

View File

@@ -0,0 +1,36 @@
#ifndef NULLSOFT_AUTH_LOGINCOMMAND_HEADER
#define NULLSOFT_AUTH_LOGINCOMMAND_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "./loginResult.h"
class LoginData;
class LoginCredentials;
class __declspec(novtable) LoginCommand
{
protected:
LoginCommand() {}
~LoginCommand() {}
public:
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
virtual HRESULT GetType(GUID *commandUid) = 0;
virtual HRESULT SetParameter(LPCWSTR pszKey, LPCWSTR pszValue) = 0;
virtual HRESULT IsValid() = 0;
virtual HRESULT IsIdentical(LoginCommand *test) = 0;
virtual HRESULT BeginLogin(LoginData *data, LoginResult::Callback callback, void *user, LoginResult **result) = 0;
virtual HRESULT EndLogin(LoginResult *result, INT *authCode, LoginCredentials **credentials) = 0;
virtual HRESULT RequestAbort(LoginResult *result, BOOL drop) = 0;
};
#endif //NULLSOFT_AUTH_LOGINCOMMAND_HEADER

View File

@@ -0,0 +1,124 @@
#include "./loginConfig.h"
#include "./common.h"
#include <shlwapi.h>
#include <strsafe.h>
#define BOOL2HRESULT(__result) ((FALSE != (__result)) ? S_OK : S_FALSE)
LoginConfig::LoginConfig()
: ref(1), configPath(NULL), pathValidated(FALSE), buffer(NULL)
{
}
LoginConfig::~LoginConfig()
{
LoginBox_FreeAnsiString(configPath);
LoginBox_FreeString((LPWSTR)buffer);
}
HRESULT LoginConfig::CreateInstance(LoginConfig **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
WCHAR szFile[MAX_PATH] = {0};
HRESULT hr;
hr = LoginBox_GetConfigPath(szFile, FALSE);
if (FAILED(hr)) return hr;
if (FALSE == PathAppend(szFile, L"loginBox.ini"))
return E_UNEXPECTED;
LPSTR configPath;
hr = LoginBox_WideCharToMultiByte(CP_UTF8, 0, szFile, -1, NULL, NULL, &configPath);
if (FAILED(hr)) return hr;
*instance = new LoginConfig();
if (NULL == *instance)
{
LoginBox_FreeAnsiString(configPath);
return E_OUTOFMEMORY;
}
else
{
(*instance)->configPath = configPath;
}
return S_OK;
}
ULONG LoginConfig::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginConfig::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginConfig::GetPath(LPCSTR *ppPath)
{
if (NULL == ppPath)
return E_POINTER;
*ppPath = configPath;
return S_OK;
}
DWORD LoginConfig::ReadAnsiStr(LPCSTR lpSectionName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize)
{
return GetPrivateProfileStringA(lpSectionName, lpKeyName, lpDefault, lpReturnedString, nSize, configPath);
}
UINT LoginConfig::ReadInt(LPCSTR lpSectionName, LPCSTR lpKeyName, INT nDefault)
{
return GetPrivateProfileIntA(lpSectionName, lpKeyName, nDefault, configPath);
}
HRESULT LoginConfig::WriteAnsiStr(LPCSTR lpSectionName, LPCSTR lpKeyName, LPCSTR lpString)
{
if (NULL == configPath || L'\0' == *configPath)
return E_UNEXPECTED;
if (FALSE == pathValidated)
{
LPWSTR pszTest;
if (SUCCEEDED(LoginBox_MultiByteToWideChar(CP_UTF8, 0, configPath, -1, &pszTest)))
{
PathRemoveFileSpec(pszTest);
LoginBox_EnsurePathExist(pszTest);
pathValidated = TRUE;
LoginBox_FreeString(pszTest);
}
}
if (0 != WritePrivateProfileStringA(lpSectionName, lpKeyName, lpString, configPath))
return S_OK;
DWORD errorCode = GetLastError();
return HRESULT_FROM_WIN32(errorCode);
}
HRESULT LoginConfig::WriteInt(LPCSTR lpSectionName, LPCSTR lpKeyName, INT nValue)
{
CHAR szBuffer[32] = {0};
HRESULT hr = StringCchPrintfA(szBuffer, ARRAYSIZE(szBuffer), "%d", nValue);
if (FAILED(hr)) return hr;
return WriteAnsiStr(lpSectionName, lpKeyName, szBuffer);
}

View File

@@ -0,0 +1,40 @@
#ifndef NULLSOFT_AUTH_LOGIN_CONFIG_HEADER
#define NULLSOFT_AUTH_LOGIN_CONFIG_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginConfig
{
protected:
LoginConfig();
~LoginConfig();
public:
static HRESULT CreateInstance(LoginConfig **instance);
public:
ULONG AddRef();
ULONG Release();
public:
HRESULT GetPath(LPCSTR *ppPath);
DWORD ReadAnsiStr(LPCSTR lpSectionName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize);
UINT ReadInt(LPCSTR lpSectionName, LPCSTR lpKeyName, INT nDefault);
HRESULT WriteAnsiStr(LPCSTR lpSectionName, LPCSTR lpKeyName, LPCSTR lpString);
HRESULT WriteInt(LPCSTR lpSectionName, LPCSTR lpKeyName, INT nValue);
protected:
ULONG ref;
LPSTR configPath;
BOOL pathValidated;
void *buffer;
};
#endif //NULLSOFT_AUTH_LOGIN_CONFIG_HEADER

View File

@@ -0,0 +1,108 @@
#include "./loginCredentials.h"
#include "./common.h"
#include "../api_auth.h"
LoginCredentials::LoginCredentials(const GUID *pRealm, LPCWSTR pszName, LPCSTR pszSession, LPCSTR pszToken, __time64_t tExpire)
: ref(1), username(NULL), sessionKey(NULL), token(NULL)
{
realm = (NULL == pRealm) ? GUID_NULL : *pRealm;
username = LoginBox_CopyString(pszName);
sessionKey = LoginBox_CopyAnsiString(pszSession);
token = LoginBox_CopyAnsiString(pszToken);
expire = tExpire;
}
LoginCredentials::~LoginCredentials()
{
LoginBox_FreeStringSecure(username);
LoginBox_FreeAnsiStringSecure(sessionKey);
LoginBox_FreeAnsiStringSecure(token);
}
HRESULT LoginCredentials::CreateInstance(const GUID *pRealm, LPCWSTR pszName, LPCSTR pszSession, LPCSTR pszToken, __time64_t tExpire, LoginCredentials **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new LoginCredentials(pRealm, pszName, pszSession, pszToken, tExpire);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT LoginCredentials::CreateFromAuth(api_auth *authApi, const GUID *pRealm, LoginCredentials **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
if (NULL == authApi) return E_INVALIDARG;
const size_t sessionKeyMax(8192), tokenMax(8192), usernameMax(8192);
LPSTR sessionKey = LoginBox_MallocAnsiString(sessionKeyMax);
LPSTR token = LoginBox_MallocAnsiString(tokenMax);
LPWSTR username = LoginBox_MallocString(usernameMax);
__time64_t expire;
HRESULT hr;
if (NULL == sessionKey || NULL == token || NULL == username)
hr = E_OUTOFMEMORY;
else
{
INT result = authApi->GetCredentials((NULL != pRealm) ? *pRealm : GUID_NULL, sessionKey, sessionKeyMax, token, tokenMax, username, usernameMax, &expire);
if (AUTH_SUCCESS == result)
{
hr = CreateInstance(pRealm, username, sessionKey, token, expire, instance);
}
else
{
hr = E_FAIL;
}
}
LoginBox_FreeAnsiStringSecure(sessionKey);
LoginBox_FreeAnsiStringSecure(token);
LoginBox_FreeStringSecure(username);
return hr;
}
UINT LoginCredentials::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
UINT LoginCredentials::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
GUID LoginCredentials::GetRealm()
{
return realm;
}
__time64_t LoginCredentials::GetExpiration()
{
return expire;
}
LPCWSTR LoginCredentials::GetUsername()
{
return username;
}
LPCSTR LoginCredentials::GetSessionKey()
{
return sessionKey;
}
LPCSTR LoginCredentials::GetToken()
{
return token;
}

View File

@@ -0,0 +1,42 @@
#ifndef NULLSOFT_AUTH_LOGIN_CREDENTIALS_HEADER
#define NULLSOFT_AUTH_LOGIN_CREDENTIALS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class api_auth;
class LoginCredentials
{
protected:
LoginCredentials(const GUID *pRealm, LPCWSTR pszName, LPCSTR pszSession, LPCSTR pszToken, __time64_t tExpire);
~LoginCredentials();
public:
static HRESULT CreateInstance(const GUID *pRealm, LPCWSTR pszName, LPCSTR pszSession, LPCSTR pszToken, __time64_t tExpire, LoginCredentials **instance);
static HRESULT CreateFromAuth(api_auth *authApi, const GUID *pRealm, LoginCredentials **instance);
public:
UINT AddRef();
UINT Release();
GUID GetRealm();
LPCWSTR GetUsername();
LPCSTR GetSessionKey();
LPCSTR GetToken();
__time64_t GetExpiration();
private:
ULONG ref;
GUID realm;
LPWSTR username;
LPSTR sessionKey;
LPSTR token;
__time64_t expire;
};
#endif //NULLSOFT_AUTH_LOGIN_CREDENTIALS_HEADER

View File

@@ -0,0 +1,544 @@
#include "./loginCurtain.h"
#include "./loginPopup.h"
#include "./common.h"
#include "./graphics.h"
#include "./imageLoader.h"
#include "../resource.h"
#include "../api.h"
#define NWC_LOGINCURTAIN L"NullsoftLoginCurtain"
typedef struct __LOGINCURTAINCREATEPARAM
{
HWND owner;
} LOGINCURTAINCREATEPARAM;
#define NLPF_IMAGEINVALID 0x00000001
typedef struct __LOGINCURTAIN
{
HWND owner;
HBITMAP bkImage;
UINT flags;
UINT childCount;
} LOGINCURTAIN;
typedef struct __DRAWBORDERPARAM
{
HWND hParent;
RECT rect;
HDC hdc;
HDC hdcSrc;
HBITMAP bitmapFrame;
HBITMAP bitmapOrig;
BLENDFUNCTION blendFunc;
} DRAWBORDERPARAM;
typedef struct __UPDATEPOSPARAM
{
HWND hParent;
RECT clientRect;
RECT childRect;
HDWP hdwp;
UINT childCount;
} UPDATEPOSPARAM;
typedef struct __EXCLUDERGNPARAM
{
HWND hParent;
HRGN exclude;
HRGN tmp;
RECT rect;
} EXCLUDERGNPARAM;
#define BACKGROUND_ALPHA 200
#define GetCurtain(__hwnd) ((LOGINCURTAIN*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0))
static LRESULT WINAPI LoginCurtain_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static BOOL LoginCurtain_RegisterClass(HINSTANCE hInstance)
{
WNDCLASSW wc;
if (FALSE != GetClassInfo(hInstance, NWC_LOGINCURTAIN, &wc))
return TRUE;
ZeroMemory(&wc, sizeof(wc));
wc.lpszClassName = NWC_LOGINCURTAIN;
wc.lpfnWndProc = LoginCurtain_WindowProc;
wc.style = CS_PARENTDC;
wc.cbWndExtra = sizeof(LOGINCURTAIN*);
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
return ( 0 != RegisterClassW(&wc));
}
HWND LoginCurtain_CreateWindow(HWND hParent, HWND hOwner)
{
if (FALSE == LoginCurtain_RegisterClass(WASABI_API_ORIG_HINST))
return NULL;
RECT rect;
if (FALSE == GetClientRect(hOwner, &rect))
SetRectEmpty(&rect);
else
MapWindowPoints(hOwner, hParent, (POINT*)&rect, 2);
LOGINCURTAINCREATEPARAM createParam;
createParam.owner = hOwner;
return CreateWindowEx(WS_EX_CONTROLPARENT, NWC_LOGINCURTAIN, NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | DS_CONTROL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
hParent, NULL, WASABI_API_ORIG_HINST, &createParam);
}
static BOOL CALLBACK LoginCurtain_ExcludeChildRgnCallback(HWND hwnd, LPARAM lParam)
{
EXCLUDERGNPARAM *param = (EXCLUDERGNPARAM*)lParam;
if (NULL == param) return FALSE;
RECT *r = &param->rect;
if (0 == (WS_VISIBLE & GetWindowStyle(hwnd)) ||
param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) ||
FALSE == GetWindowRect(hwnd, r))
return TRUE;
MapWindowPoints(HWND_DESKTOP, param->hParent, (POINT*)r, 2);
if (NULL == param->tmp)
{
param->tmp = CreateRectRgn(0, 0, 0, 0);
if (NULL == param->tmp) return FALSE;
}
if (NULL == param->exclude)
{
param->exclude = CreateRectRgn(0, 0, 0, 0);
if (NULL == param->exclude) return FALSE;
}
INT regionType = GetWindowRgn(hwnd, param->tmp);
switch(regionType)
{
case NULLREGION:
SetRectRgn(param->tmp, r->left, r->top, r->right, r->bottom);
CombineRgn(param->exclude, param->exclude, param->tmp, RGN_OR);
break;
case SIMPLEREGION:
case COMPLEXREGION:
OffsetRgn(param->tmp, r->left, r->top);
CombineRgn(param->exclude, param->exclude, param->tmp, RGN_OR);
break;
}
return TRUE;
}
static void LoginCurtain_ExcludeChildren(HWND hwnd, HDC hdc)
{
EXCLUDERGNPARAM param;
param.hParent = hwnd;
param.exclude = NULL;
param.tmp = NULL;
EnumChildWindows(hwnd, LoginCurtain_ExcludeChildRgnCallback, (LPARAM)&param);
if (NULL != param.exclude)
{
ExtSelectClipRgn(hdc, param.exclude, RGN_DIFF);
DeleteObject(param.exclude);
}
if (NULL != param.tmp)
DeleteObject(param.tmp);
}
static BOOL CALLBACK LoginCurtain_DrawWindowBorderCallback(HWND hwnd, LPARAM lParam)
{
DRAWBORDERPARAM *param = (DRAWBORDERPARAM*)lParam;
if (NULL == param) return FALSE;
RECT *r = &param->rect;
if (0 == (WS_VISIBLE & GetWindowStyle(hwnd)) ||
param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) ||
FALSE == GetWindowRect(hwnd, r))
return TRUE;
MapWindowPoints(HWND_DESKTOP, param->hParent, (POINT*)r, 2);
if (NULL == param->bitmapFrame)
{
INT frameHeight, frameWidth;
param->bitmapFrame = ImageLoader_LoadBitmap(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_POPUPBORDER_IMAGE),
TRUE, &frameWidth, &frameHeight);
if (NULL == param->bitmapFrame)
return FALSE;
param->hdcSrc = CreateCompatibleDC(param->hdc);
if (NULL == param->hdcSrc) return FALSE;
param->bitmapOrig = (HBITMAP)SelectObject(param->hdcSrc, param->bitmapFrame);
param->blendFunc.AlphaFormat = AC_SRC_ALPHA;
param->blendFunc.BlendFlags = 0;
param->blendFunc.BlendOp = AC_SRC_OVER;
param->blendFunc.SourceConstantAlpha = 255;
}
r->left -= 14;
r->top -= 13;
r->right += 17;
r->bottom += 19;
GdiAlphaBlend(param->hdc, r->left, r->top, 26, 26, param->hdcSrc, 0, 0, 26, 26, param->blendFunc);
GdiAlphaBlend(param->hdc, r->right - 28, r->top, 28, 26, param->hdcSrc, 27, 0, 28, 26, param->blendFunc);
GdiAlphaBlend(param->hdc, r->left, r->bottom - 31, 26, 31, param->hdcSrc, 0, 27, 26, 31, param->blendFunc);
GdiAlphaBlend(param->hdc, r->right - 28, r->bottom - 31, 28, 31, param->hdcSrc, 27, 27, 28, 31, param->blendFunc);
LONG l = (r->right - r->left - (26 + 28));
GdiAlphaBlend(param->hdc, r->left + 26, r->top, l, 26, param->hdcSrc, 25, 0, 1, 26, param->blendFunc);
GdiAlphaBlend(param->hdc, r->left + 26, r->bottom - 31, l, 31, param->hdcSrc, 25, 27, 1, 31, param->blendFunc);
l = (r->bottom - r->top - (26 + 31));
GdiAlphaBlend(param->hdc, r->left, r->top + 26, 26, l, param->hdcSrc, 0, 28, 26, 1, param->blendFunc);
GdiAlphaBlend(param->hdc, r->right - 28, r->top + 26, 28, l, param->hdcSrc, 27, 28, 28, 1, param->blendFunc);
return TRUE;
}
static void LoginCurtain_DrawChildBorders(HWND hwnd, HDC hdc)
{
DRAWBORDERPARAM param;
ZeroMemory(&param, sizeof(param));
param.hdc = hdc;
param.hParent = hwnd;
EnumChildWindows(hwnd, LoginCurtain_DrawWindowBorderCallback, (LPARAM)&param);
if (NULL != param.hdcSrc)
{
SelectObject(param.hdcSrc, param.bitmapOrig);
DeleteDC(param.hdcSrc);
}
if (NULL != param.bitmapFrame)
DeleteObject(param.bitmapFrame);
}
static HBITMAP LoginCurtain_CreateBkImage(HWND hwnd, HDC hdc, HBITMAP hBitmap, HWND hOwner)
{
RECT rect;
if (FALSE == GetClientRect(hwnd, &rect))
return NULL;
LONG width = rect.right - rect.left;
LONG height = rect.bottom - rect.top;
BITMAP bi;
if (NULL == hBitmap ||
sizeof(BITMAP) != GetObject(hBitmap, sizeof(BITMAP), &bi) ||
bi.bmWidth < width || bi.bmHeight < height)
{
if (NULL != hBitmap)
DeleteObject(hBitmap);
BITMAPINFOHEADER header;
ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
header.biSize = sizeof(BITMAPINFOHEADER);
header.biCompression = BI_RGB;
header.biBitCount = 32;
header.biPlanes = 1;
header.biWidth = (width + 32);
header.biHeight = -(height + 32);
bi.bmBitsPixel = header.biBitCount;
bi.bmWidth = header.biWidth;
bi.bmHeight = header.biHeight;
bi.bmPlanes = header.biPlanes;
hBitmap = CreateDIBSection(NULL, (LPBITMAPINFO)&header, DIB_RGB_COLORS, (void**)&bi.bmBits, NULL, 0);
if (NULL == hBitmap) return NULL;
}
else
{
bi.bmHeight = -bi.bmHeight;
}
HBRUSH bkBrush = (HBRUSH)SendMessage(hOwner, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd);
HBITMAP hbo = (HBITMAP)SelectObject(hdc, hBitmap);
if (NULL == hOwner)
{
if (NULL != bkBrush)
FillRect(hdc, &rect, bkBrush);
else
ExtTextOut(hdc, 0, 0, OPAQUE, &rect, NULL, 0, NULL);
}
else
{
if (FALSE == LoginBox_PrintWindow(hOwner, hdc, 0))
SendMessage(hOwner, WM_PRINT, (WPARAM)hdc, (LPARAM) (PRF_NONCLIENT | PRF_CLIENT | PRF_CHILDREN | PRF_ERASEBKGND));
COLORREF rgbBlend = GetDCBrushColor(hdc);
if (CLR_INVALID == rgbBlend)
rgbBlend = GetBkColor(hdc);
rgbBlend |= (BACKGROUND_ALPHA << 24);
Image_ColorOverEx((BYTE*)bi.bmBits, bi.bmWidth, bi.bmHeight, 0, 0, width, height, bi.bmBitsPixel, FALSE, rgbBlend);
}
LoginCurtain_DrawChildBorders(hwnd, hdc);
SelectObject(hdc, hbo);
return hBitmap;
}
static void LoginCurtain_EraseBkGround(HWND hwnd, HDC hdc, const RECT *prcPaint)
{
LOGINCURTAIN *curtain = GetCurtain(hwnd);
if (NULL == curtain) return;
HDC hdcSrc = CreateCompatibleDC(hdc);
if (NULL == hdcSrc) return;
if (NULL == curtain->bkImage || 0 != (NLPF_IMAGEINVALID & curtain->flags))
{
HRGN clipRegion = CreateRectRgn(0,0,0,0);
if (NULL != clipRegion)
{
INT regionType = GetClipRgn(hdc, clipRegion);
if (1 == regionType)
SelectClipRgn(hdcSrc, clipRegion);
DeleteObject(clipRegion);
}
curtain->bkImage = LoginCurtain_CreateBkImage(hwnd, hdcSrc, curtain->bkImage, curtain->owner);
curtain->flags &= ~NLPF_IMAGEINVALID;
}
if (NULL != curtain->bkImage)
{
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcSrc, curtain->bkImage);
BitBlt(hdc, prcPaint->left, prcPaint->top,
prcPaint->right - prcPaint->left, prcPaint->bottom - prcPaint->top,
hdcSrc, prcPaint->left, prcPaint->top, SRCCOPY);
SelectObject(hdcSrc, hbmpOld);
}
DeleteDC(hdcSrc);
}
static void LoginCurtain_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase)
{
if (FALSE != fErase)
{
LoginCurtain_ExcludeChildren(hwnd, hdc);
LoginCurtain_EraseBkGround(hwnd, hdc, prcPaint);
}
}
static BOOL CALLBACK LoginCurtain_UpdateChildPosCallback(HWND hwnd, LPARAM lParam)
{
UPDATEPOSPARAM *param = (UPDATEPOSPARAM*)lParam;
if (NULL == param) return FALSE;
if (param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT))
return TRUE;
if (NULL == param->hdwp)
{
param->hdwp = BeginDeferWindowPos(param->childCount);
param->childCount = 0;
if (NULL == param->hdwp) return FALSE;
}
LONG prevWidth(0), prevHeight(0);
if (FALSE != GetWindowRect(hwnd, &param->childRect))
{
prevWidth = param->childRect.right - param->childRect.left;
prevHeight = param->childRect.bottom - param->childRect.top;
}
if (FALSE != LoginPopup_UpdateWindowPos(hwnd, &param->clientRect, &param->childRect))
{
param->hdwp = DeferWindowPos(param->hdwp, hwnd, NULL, param->childRect.left, param->childRect.top,
param->childRect.right - param->childRect.left, param->childRect.bottom - param->childRect.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
if (NULL == param->hdwp) return FALSE;
LONG width = param->childRect.right - param->childRect.left;
LONG height = param->childRect.bottom - param->childRect.top;
if (width != prevWidth || height != prevHeight)
{
HRGN clipRgn = CreateRoundRectRgn(0, 0, width, height, 9, 9);
SetWindowRgn(hwnd, clipRgn, FALSE);
}
}
param->childCount++;
return TRUE;
}
static void LoginCurtain_UpdateLayout(HWND hwnd, BOOL fRedraw)
{
LOGINCURTAIN *curtain = GetCurtain(hwnd);
if (NULL == curtain) return;
curtain->flags |= NLPF_IMAGEINVALID;
RECT clientRect;
GetClientRect(hwnd, &clientRect);
UPDATEPOSPARAM param;
param.hParent = hwnd;
param.hdwp = 0;
param.childCount = curtain->childCount;
CopyRect(&param.clientRect, &clientRect);
param.clientRect.left += 15;
param.clientRect.top += 14;
param.clientRect.right -= 18;
param.clientRect.bottom -= 20;
EnumChildWindows(hwnd, LoginCurtain_UpdateChildPosCallback, (LPARAM)&param);
curtain->childCount = param.childCount;
if (NULL != param.hdwp)
EndDeferWindowPos(param.hdwp);
if (FALSE != fRedraw)
{
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN);
}
}
static LRESULT LoginCurtain_OnCreate(HWND hwnd, CREATESTRUCT* pcs)
{
LOGINCURTAIN *curtain = (LOGINCURTAIN*)calloc(1, sizeof(LOGINCURTAIN));
if (NULL != curtain)
{
SetLastError(ERROR_SUCCESS);
if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)curtain) && ERROR_SUCCESS != GetLastError())
{
free(curtain);
curtain = NULL;
}
}
if (NULL == curtain)
return -1;
LOGINCURTAINCREATEPARAM *createParam = (LOGINCURTAINCREATEPARAM*)pcs->lpCreateParams;
if (NULL != createParam)
{
curtain->owner = createParam->owner;
}
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOREDRAW);
return 0;
}
static void LoginCurtain_OnDestroy(HWND hwnd)
{
LOGINCURTAIN *curtain = GetCurtain(hwnd);
SetWindowLongPtr(hwnd, 0, 0L);
if (NULL == curtain) return;
if (NULL != curtain->bkImage)
DeleteObject(curtain->bkImage);
free(curtain);
}
static void LoginCurtain_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp)
{
if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
return;
LoginCurtain_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags));
}
static void LoginCurtain_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
if (BeginPaint(hwnd, &ps))
{
if (ps.rcPaint.left != ps.rcPaint.right)
LoginCurtain_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
EndPaint(hwnd, &ps);
}
}
static void LoginCurtain_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
{
RECT clientRect;
if (GetClientRect(hwnd, &clientRect))
LoginCurtain_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options));
}
static void LoginCurtain_OnParentNotify(HWND hwnd, INT eventId, INT childId, LPARAM eventParam)
{
switch(eventId)
{
case WM_CREATE:
{
HWND hChild = (HWND)eventParam;
RECT rect;
GetWindowRect(hChild, &rect);
HRGN clipRgn = CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, 9, 9);
SetWindowRgn(hChild, clipRgn, FALSE);
}
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED );
break;
case WM_DESTROY:
{
HWND hChild = (HWND)eventParam;
SetWindowLongPtr(hChild, GWLP_ID, 0);
}
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
break;
}
}
static LRESULT LoginCurtain_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh)
{
HWND hAncestor = GetAncestor(hwnd, GA_PARENT);
if (NULL != hAncestor)
return SendMessage(hAncestor, WM_NOTIFY, (WPARAM)controlId, (LPARAM)pnmh);
return 0;
}
static LRESULT WINAPI LoginCurtain_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: return LoginCurtain_OnCreate(hwnd, (CREATESTRUCT*)lParam);
case WM_DESTROY: LoginCurtain_OnDestroy(hwnd); return 0;
case WM_ERASEBKGND: return 0;
case WM_PAINT: LoginCurtain_OnPaint(hwnd); return 0;
case WM_PRINTCLIENT: LoginCurtain_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0;
case WM_WINDOWPOSCHANGED: LoginCurtain_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
case WM_SIZE: return 0;
case WM_PARENTNOTIFY: LoginCurtain_OnParentNotify(hwnd, LOWORD(wParam), HIWORD(wParam), lParam); return 0;
case WM_NOTIFY: return LoginCurtain_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,12 @@
#ifndef NULLSOFT_AUTH_LOGINCURTAIN_HEADER
#define NULLSOFT_AUTH_LOGINCURTAIN_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
HWND LoginCurtain_CreateWindow(HWND hParent, HWND hOwner);
#endif //NULLSOFT_AUTH_LOGINCURTAIN_HEADER

View File

@@ -0,0 +1,149 @@
#include "./loginData.h"
#include "./loginBox.h"
#include "./loginProvider.h"
#include "./loginStatus.h"
#include "../api.h"
LoginData::LoginData(const GUID *pRealm, HWND hPage, HWND hLoginbox)
: ref(1), hPage(hPage), hLoginbox(hLoginbox), provider(NULL), status(NULL), statusCookie(-1)
{
if (NULL != pRealm)
{
realm = *pRealm;
}
else
{
if (NULL == hLoginbox || FALSE == LoginBox_GetRealm(hLoginbox, &realm))
realm = GUID_NULL;
}
if (FALSE == LoginBox_GetActiveProvider(hLoginbox, &provider))
provider = NULL;
LoginBox_GetStatus(hLoginbox, &status);
}
LoginData::~LoginData()
{
if (NULL != provider)
provider->Release();
if (NULL != status)
{
if (-1 != statusCookie)
status->Remove(statusCookie);
status->Release();
}
}
HRESULT LoginData::CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LoginData **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hPage || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginData(pRealm, hPage, hLoginbox);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
ULONG LoginData::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginData::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginData::QueryInterface(REFIID riid, void** ppObject)
{
if (NULL == ppObject)
return E_POINTER;
if (IsEqualIID(riid, IID_LoginData))
*ppObject = static_cast<LoginData*>(this);
else
{
*ppObject = NULL;
return E_NOINTERFACE;
}
if (NULL == *ppObject)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
HWND LoginData::GetLoginbox()
{
return hLoginbox;
}
HWND LoginData::GetPage()
{
return hPage;
}
HRESULT LoginData::GetRealm(GUID *pRealm)
{
if (NULL == pRealm) return E_POINTER;
*pRealm = realm;
return S_OK;
}
HRESULT LoginData::GetProvider(LoginProvider **ppProvider)
{
if (NULL == ppProvider) return E_POINTER;
*ppProvider = provider;
if (NULL != provider)
provider->AddRef();
return S_OK;
}
HRESULT LoginData::GetStatus(LoginStatus **ppStatus)
{
if (NULL == ppStatus) return E_POINTER;
*ppStatus = status;
if (NULL != status)
status->AddRef();
return S_OK;
}
HRESULT LoginData::SetStatus(LPCWSTR pszStatus)
{
if (NULL == status)
return E_FAIL;
BSTR bstrText;
if (NULL == pszStatus || FALSE == IS_INTRESOURCE(pszStatus))
bstrText = SysAllocString(pszStatus);
else
{
WCHAR szBuffer[256] = {0};
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)pszStatus, szBuffer, ARRAYSIZE(szBuffer));
bstrText = SysAllocString(szBuffer);
}
if (-1 == statusCookie)
{
statusCookie = status->Add(bstrText);
if (-1 == statusCookie)
return E_FAIL;
}
else
{
if (FALSE == status->Set(statusCookie, bstrText))
return E_FAIL;
}
return S_OK;
}

View File

@@ -0,0 +1,50 @@
#ifndef NULLSOFT_AUTH_LOGINDATA_HEADER
#define NULLSOFT_AUTH_LOGINDATA_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
// {69346B92-168E-452e-AA88-986AB3883920}
static const GUID IID_LoginData =
{ 0x69346b92, 0x168e, 0x452e, { 0xaa, 0x88, 0x98, 0x6a, 0xb3, 0x88, 0x39, 0x20 } };
class LoginProvider;
class LoginStatus;
class LoginData
{
protected:
LoginData(const GUID *pRealm, HWND hPage, HWND hLoginbox);
virtual ~LoginData();
public:
static HRESULT CreateInstance(const GUID *pRealm, HWND hPage, HWND hLoginbox, LoginData **instance);
public:
virtual ULONG AddRef();
virtual ULONG Release();
virtual HRESULT QueryInterface(REFIID riid, void** ppObject);
virtual HWND GetLoginbox();
virtual HWND GetPage();
virtual HRESULT GetRealm(GUID *pRealm);
virtual HRESULT GetProvider(LoginProvider **ppProvider);
virtual HRESULT GetStatus(LoginStatus **ppStatus);
virtual HRESULT SetStatus(LPCWSTR pszStatus);
protected:
UINT ref;
GUID realm;
HWND hPage;
HWND hLoginbox;
LoginProvider *provider;
LoginStatus *status;
UINT statusCookie;
};
#endif //NULLSOFT_AUTH_LOGINDATA_HEADER

View File

@@ -0,0 +1,277 @@
#include "./loginGui.h"
#include "./common.h"
#include "./imageLoader.h"
#include "../resource.h"
#include "../api.h"
#include <strsafe.h>
static size_t threadStorage = TLS_OUT_OF_INDEXES;
LoginGuiObject::LoginGuiObject()
: ref(1), bitmapIcons(NULL), fontTitle(NULL), fontEditor(NULL), fontText(NULL)
{
}
LoginGuiObject::~LoginGuiObject()
{
Reset();
}
HRESULT LoginGuiObject::InitializeThread()
{
if (TLS_OUT_OF_INDEXES == threadStorage)
{
if (NULL == WASABI_API_APP)
return E_UNEXPECTED;
threadStorage = WASABI_API_APP->AllocateThreadStorage();
if (TLS_OUT_OF_INDEXES == threadStorage)
return E_UNEXPECTED;
}
LoginGuiObject *cache = (LoginGuiObject*)WASABI_API_APP->GetThreadStorage(threadStorage);
if (NULL != cache)
{
cache->AddRef();
return S_FALSE;
}
if (NULL == cache)
{
cache = new LoginGuiObject();
if (NULL == cache) return E_OUTOFMEMORY;
WASABI_API_APP->SetThreadStorage(threadStorage, cache);
}
return S_OK;
}
HRESULT LoginGuiObject::UninitializeThread()
{
if (TLS_OUT_OF_INDEXES == threadStorage)
return E_FAIL;
if (NULL == WASABI_API_APP)
return E_UNEXPECTED;
LoginGuiObject *cache = (LoginGuiObject*)WASABI_API_APP->GetThreadStorage(threadStorage);
if (NULL != cache && 0 == cache->Release())
WASABI_API_APP->SetThreadStorage(threadStorage, NULL);
return S_OK;
}
HRESULT LoginGuiObject::QueryInstance(LoginGuiObject **instance)
{
if (NULL == instance)
return E_POINTER;
if (TLS_OUT_OF_INDEXES == threadStorage)
return E_UNEXPECTED;
*instance = (LoginGuiObject*)WASABI_API_APP->GetThreadStorage(threadStorage);
if (NULL == *instance) return E_FAIL;
(*instance)->AddRef();
return S_OK;
}
ULONG LoginGuiObject::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginGuiObject::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginGuiObject::Reset()
{
if (NULL != bitmapIcons)
{
DeleteObject(bitmapIcons);
bitmapIcons = NULL;
}
if (NULL != fontTitle)
{
DeleteObject(fontTitle);
fontTitle = NULL;
}
if (NULL != fontEditor)
{
DeleteObject(fontEditor);
fontEditor = NULL;
}
if (NULL != fontText)
{
DeleteObject(fontText);
fontText = NULL;
}
return S_OK;
}
HRESULT LoginGuiObject::GetIconDimensions(INT *pWidth, INT *pHeight)
{
if (NULL == bitmapIcons)
{
INT width, height;
bitmapIcons = ImageLoader_LoadBitmap(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_NOTIFIERICONS_IMAGE),
TRUE, &width, &height);
if (NULL == bitmapIcons)
return E_FAIL;
if (height < 0) height = -height;
if (NULL != pWidth) *pWidth = width;
if (NULL != pHeight) *pHeight = width;
return S_OK;
}
BITMAP bm;
if (sizeof(bm) != GetObject(bitmapIcons, sizeof(bm), &bm))
return E_FAIL;
if (NULL != pWidth) *pWidth = bm.bmWidth;
if (NULL != pHeight) *pHeight = bm.bmWidth;
return S_OK;
}
HBITMAP LoginGuiObject::GetIcon(INT iconId, RECT *prcIcon)
{
if (NULL == prcIcon || iconId < 0)
return NULL;
INT width, height;
if (NULL != bitmapIcons)
{
BITMAP bm;
if (sizeof(bm) != GetObject(bitmapIcons, sizeof(bm), &bm))
bitmapIcons = NULL;
else
{
width = bm.bmWidth;
height = bm.bmHeight;
}
}
if (NULL == bitmapIcons)
{
bitmapIcons = ImageLoader_LoadBitmap(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_NOTIFIERICONS_IMAGE),
TRUE, &width, &height);
if (NULL == bitmapIcons)
return NULL;
}
if (height < 0) height = -height;
if (width * (iconId + 1) > height)
return NULL;
prcIcon->left = 0;
prcIcon->right = width;
prcIcon->top = width * iconId;
prcIcon->bottom = prcIcon->top + width;
return bitmapIcons;
}
static HFONT LoginGuiObject_DuplicateFont(HFONT fontBase, INT heightDeltaPt)
{
if (NULL == fontBase) return NULL;
LOGFONT lf;
if (sizeof(lf) != GetObject(fontBase, sizeof(lf), &lf))
return NULL;
if (0 != heightDeltaPt)
{
HDC hdc = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE | DCX_NORESETATTRS);
HDC hdcTmp = NULL;
if (NULL != hdc)
{
hdcTmp = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
}
if (NULL == hdcTmp)
return NULL;
LONG pixelsY = GetDeviceCaps (hdcTmp, LOGPIXELSY);
HFONT fontOrig = (HFONT)SelectObject(hdcTmp, fontBase);
TEXTMETRIC tm;
if (FALSE != GetTextMetrics(hdcTmp, &tm))
{
INT basePt = MulDiv(tm.tmHeight - tm.tmInternalLeading, 72, pixelsY);
lf.lfHeight = -MulDiv((basePt + heightDeltaPt), pixelsY, 72);
}
SelectObject(hdcTmp, fontOrig);
DeleteDC(hdcTmp);
}
return CreateFontIndirect(&lf);
}
HFONT LoginGuiObject::GetTitleFont()
{
if (NULL == fontTitle)
{
HFONT fontBase = GetTextFont();
if (NULL != fontBase)
{
fontTitle = LoginGuiObject_DuplicateFont(fontBase, 3);
}
}
return fontTitle;
}
HFONT LoginGuiObject::GetEditorFont()
{
if (NULL == fontEditor)
{
HFONT fontBase = GetTextFont();
if (NULL != fontBase)
{
fontEditor = LoginGuiObject_DuplicateFont(fontBase, 0);
}
}
return fontEditor;
}
HFONT LoginGuiObject::GetTextFont()
{
if (NULL == fontText)
{
LOGFONT lf;
if (FALSE != SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
{
lf.lfQuality = LoginBox_GetSysFontQuality();
fontText = CreateFontIndirect(&lf);
}
}
return fontText;
}

View File

@@ -0,0 +1,53 @@
#ifndef NULLSOFT_AUTH_LOGIN_GUI_OBJECT_HEADER
#define NULLSOFT_AUTH_LOGIN_GUI_OBJECT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginGuiObject
{
public:
typedef enum
{
iconNone = -1,
iconInfo = 0,
iconWarning = 1,
iconError = 2,
iconQuestion = 3,
} IconType;
protected:
LoginGuiObject();
~LoginGuiObject();
public:
static HRESULT InitializeThread();
static HRESULT UninitializeThread();
static HRESULT QueryInstance(LoginGuiObject **instance);
public:
ULONG AddRef();
ULONG Release();
HRESULT Reset();
HRESULT GetIconDimensions(INT *pWidth, INT *pHeight);
HBITMAP GetIcon(INT iconId, RECT *prcIcon);
HFONT GetTitleFont();
HFONT GetEditorFont();
HFONT GetTextFont();
private:
ULONG ref;
HBITMAP bitmapIcons;
HFONT fontTitle;
HFONT fontEditor;
HFONT fontText;
};
#endif //NULLSOFT_AUTH_LOGIN_GUI_OBJECT_HEADER

View File

@@ -0,0 +1,663 @@
#define OEMRESOURCE
#include "./loginNotifier.h"
#include "./common.h"
#include "./loginGui.h"
#include "../api.h"
#include "../resource.h"
#include "../api_auth.h"
#include <strsafe.h>
#define NWC_LOGINNOTIFIER L"NullsoftLoginNotifier"
#define GRADIENT_LEFT 30
#define GRADIENT_RIGHT 10
#define SPACING_TOP 2
#define SPACING_BOTTOM 2
typedef struct __LOGINNOTIFIER
{
UINT flags;
HBITMAP image;
INT type;
LPWSTR text;
HFONT font;
INT textHeight;
INT aveCharWidth;
COLORREF rgbBack;
COLORREF rgbText;
} LOGINNOTIFIER;
#define GetNotifier(__hwnd) ((LOGINNOTIFIER*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0))
static LRESULT WINAPI LoginNotifier_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static BOOL LoginNotifier_RegisterClass(HINSTANCE hInstance)
{
WNDCLASSW wc;
if (FALSE != GetClassInfo(hInstance, NWC_LOGINNOTIFIER, &wc))
return TRUE;
ZeroMemory(&wc, sizeof(wc));
wc.lpszClassName = NWC_LOGINNOTIFIER;
wc.lpfnWndProc = LoginNotifier_WindowProc;
wc.style = CS_PARENTDC;
wc.cbWndExtra = sizeof(LOGINNOTIFIER*);
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
return ( 0 != RegisterClassW(&wc));
}
HWND LoginNotifier_CreateWindow(UINT styleEx, UINT style, INT x, INT y, INT cx, INT cy, HWND hParent, INT controlId)
{
if (FALSE == LoginNotifier_RegisterClass(WASABI_API_ORIG_HINST))
return NULL;
return CreateWindowEx(styleEx, NWC_LOGINNOTIFIER, NULL, WS_CHILD | style, x, y, cx, cy,
hParent, (HMENU)(INT_PTR)controlId, WASABI_API_ORIG_HINST, NULL);
}
static HBITMAP LoginNotifier_CreateTypeImage(HDC hdc, INT type, INT height)
{
INT iconIndex;
COLORREF rgbBack = RGB(255, 255, 255);
COLORREF rgbAlert;
switch(type)
{
case NLNTYPE_INFORMATION:
iconIndex = LoginGuiObject::iconInfo;
rgbAlert = RGB(209, 222, 254);
break;
case NLNTYPE_WARNING:
iconIndex = LoginGuiObject::iconWarning;
rgbAlert = RGB(254, 241, 148);
break;
case NLNTYPE_ERROR:
iconIndex = LoginGuiObject::iconError;
rgbAlert = RGB(225, 105, 105);
break;
case NLNTYPE_QUESTION:
iconIndex = LoginGuiObject::iconQuestion;
rgbAlert = RGB(209, 222, 254);
break;
default:
iconIndex = LoginGuiObject::iconNone;
rgbAlert = GetSysColor(COLOR_3DLIGHT);
break;
}
RECT iconRect;
HBITMAP bitmapIcons = NULL;
if (LoginGuiObject::iconNone != iconIndex)
{
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
bitmapIcons = loginGui->GetIcon(iconIndex, &iconRect);
loginGui->Release();
}
}
if (NULL == bitmapIcons)
SetRectEmpty(&iconRect);
INT iconWidth = iconRect.right - iconRect.left;
INT iconHeight = iconRect.bottom - iconRect.top;
INT width = GRADIENT_LEFT + GRADIENT_RIGHT;
width += iconWidth;
HBITMAP bitmapDst = NULL;
HDC contextDst = CreateCompatibleDC(hdc);
if (NULL != contextDst)
{
bitmapDst = CreateCompatibleBitmap(hdc, width, height);
if (NULL != bitmapDst)
{
HBITMAP bitmapDstOrig = (HBITMAP)SelectObject(contextDst, bitmapDst);
TRIVERTEX vertex[] =
{
{ 0, 0, GetRValue(rgbBack) << 8, GetGValue(rgbBack) << 8, GetBValue(rgbBack) << 8, 0x0000 },
{ GRADIENT_LEFT, height, GetRValue(rgbAlert) << 8, GetGValue(rgbAlert) << 8, GetBValue(rgbAlert) << 8, 0x0000 },
};
GRADIENT_RECT gradientRect;
gradientRect.UpperLeft = 0;
gradientRect.LowerRight = 1;
RECT fillRect;
SetRect(&fillRect, 0, 0, width, height);
if (FALSE != GdiGradientFill(contextDst, vertex, ARRAYSIZE(vertex), &gradientRect, 1, GRADIENT_FILL_RECT_H))
fillRect.left = GRADIENT_LEFT;
if (fillRect.left < fillRect.right)
{
COLORREF rgbBackOrig = SetBkColor(contextDst, rgbAlert);
ExtTextOut(contextDst, 0, 0, ETO_OPAQUE, &fillRect, NULL, 0, NULL);
if (rgbBackOrig != rgbAlert)
SetBkColor(contextDst, rgbBackOrig);
}
if (NULL != bitmapIcons)
{
HDC contextSrc = CreateCompatibleDC(hdc);
if (NULL != contextSrc)
{
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(contextSrc, bitmapIcons);
BLENDFUNCTION blendFunc;
blendFunc.AlphaFormat = AC_SRC_ALPHA;
blendFunc.BlendFlags = 0;
blendFunc.BlendOp = AC_SRC_OVER;
blendFunc.SourceConstantAlpha = 255;
INT iconTop = (height - iconHeight)/2 + (height - iconHeight)%2;
if (iconTop >= 1 && (iconTop + iconHeight) < height)
{
GdiAlphaBlend(contextDst, GRADIENT_LEFT, iconTop, iconWidth, iconHeight,
contextSrc, iconRect.left, iconRect.top, iconWidth, iconHeight, blendFunc);
}
SelectObject(contextSrc, bitmapSrcOrig);
DeleteDC(contextSrc);
}
}
SelectObject(contextDst, bitmapDstOrig);
}
DeleteDC(contextDst);
}
return bitmapDst;
}
static INT LoginNotifier_CalcTextHeight(HWND hwnd, HDC hdc, INT *aveCharWidth)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return 0;
HDC contextMine(NULL);
HFONT fontOrig;
if (NULL == hdc)
{
contextMine = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == contextMine) return 0;
if (NULL != notifier->font)
fontOrig = (HFONT)SelectObject(contextMine, notifier->font);
hdc = contextMine;
}
TEXTMETRIC tm;
if (FALSE == GetTextMetrics(hdc, &tm))
{
tm.tmHeight = 0;
tm.tmAveCharWidth = 0;
}
if (NULL != aveCharWidth)
{
*aveCharWidth = LoginBox_GetAveCharWidth(hdc);
}
if (NULL != contextMine)
{
if (NULL != notifier->font)
SelectObject(contextMine, fontOrig);
ReleaseDC(hwnd, contextMine);
}
return tm.tmHeight;
}
static void LoginNotifier_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
RECT rect;
GetClientRect(hwnd, &rect);
if (NULL == notifier->image)
notifier->image = LoginNotifier_CreateTypeImage(hdc, notifier->type, rect.bottom - rect.top);
INT imageWidth = 0;
if (NULL != notifier->image)
{
BITMAP bm;
if (sizeof(BITMAP) == GetObject(notifier->image, sizeof(BITMAP), &bm))
{
HDC contextSrc = CreateCompatibleDC(hdc);
if (NULL != contextSrc)
{
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(contextSrc, notifier->image);
if (FALSE != BitBlt(hdc, rect.left, rect.top, bm.bmWidth, bm.bmHeight, contextSrc, 0, 0, SRCCOPY))
imageWidth = bm.bmWidth;
SelectObject(contextSrc, bitmapSrcOrig);
DeleteDC(contextSrc);
}
}
}
SetBkColor(hdc, notifier->rgbBack);
SetTextColor(hdc, notifier->rgbText);
HFONT fontOrig;
if (NULL != notifier->font)
fontOrig = (HFONT)SelectObject(hdc, notifier->font);
LPCWSTR text = notifier->text;
INT cchText = (NULL != text) ? lstrlenW(text) : 0;
if (-1 == notifier->textHeight)
notifier->textHeight = LoginNotifier_CalcTextHeight(hwnd, hdc, &notifier->aveCharWidth);
RECT textRect;
CopyRect(&textRect, &rect);
textRect.left += imageWidth;
INT textOffsetY = (textRect.bottom - textRect.top) - notifier->textHeight;
textOffsetY = textOffsetY/2 + textOffsetY%2;
if (textOffsetY < SPACING_TOP) textOffsetY = SPACING_TOP;
INT textAlignOrig = SetTextAlign(hdc, TA_TOP | TA_LEFT);
ExtTextOut(hdc, textRect.left + notifier->aveCharWidth+2, textRect.top + textOffsetY, ETO_CLIPPED | ETO_OPAQUE, &textRect, text, cchText, NULL);
if (textAlignOrig != (TA_TOP | TA_LEFT))
SetTextAlign(hdc, textAlignOrig);
if (NULL != notifier->font)
SelectObject(hdc, fontOrig);
}
static void LoginNotifier_UpdateLayout(HWND hwnd, BOOL fRedraw)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
RECT rect;
GetClientRect(hwnd, &rect);
if (NULL != notifier->image)
{
BITMAP bm;
if (sizeof(BITMAP) != GetObject(notifier->image, sizeof(BITMAP), &bm) ||
bm.bmHeight != rect.bottom - rect.top)
{
DeleteObject(notifier->image);
notifier->image = NULL;
}
}
InvalidateRect(hwnd, NULL, TRUE);
}
static BOOL LoginNotifier_SetNotification(HWND hwnd, INT type, LPCWSTR pszText, BOOL fInvalidate)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return FALSE;
if (type != notifier->type)
{
notifier->type = type;
if (NULL != notifier->image)
{
DeleteObject(notifier->image);
notifier->image = NULL;
}
}
LoginBox_FreeString(notifier->text);
BOOL resultCode = TRUE;
if (NULL == pszText)
{
notifier->text = NULL;
}
else
{
if (IS_INTRESOURCE(pszText))
{
INT stringId;
switch((INT_PTR)pszText)
{
case AUTH_SUCCESS: stringId = IDS_ERR_SUCCESS; break;
case AUTH_404: stringId = IDS_ERR_404; break;
case AUTH_TIMEOUT: stringId = IDS_ERR_TIMEOUT; break;
case AUTH_NOHTTP: stringId = IDS_ERR_NOHTTP; break;
case AUTH_NOPARSER: stringId = IDS_ERR_NOPARSER; break;
case AUTH_CONNECTIONRESET: stringId = IDS_ERR_CONNECTIONRESET; break;
case AUTH_ERROR_PARSING_XML: stringId = IDS_ERR_PARSING_XML; break;
case AUTH_NOT_AUTHORIZED: stringId = IDS_ERR_NOT_AUTHORIZED; break;
case AUTH_SECURID: stringId = IDS_ERR_SECURID; break;
case AUTH_ABORT: stringId = IDS_ERR_ABORT; break;
case AUTH_INVALIDCRED: stringId = IDS_ERR_INVALIDCRED; break;
case AUTH_UNCONFIRMED: stringId = IDS_ERR_UNCONFIRMED; break;
case AUTH_UNEXPECTED: stringId = IDS_ERR_UNEXPECTED; break;
case AUTH_INVALIDPASSCODE: stringId = IDS_ERR_PASSCODE_INVALID; break;
case AUTH_USERNAME_EMPTY: stringId = IDS_ERR_USERNAME_EMPTY; break;
case AUTH_USERNAME_TOOSHORT: stringId = IDS_ERR_USERNAME_TOOSHORT; break;
case AUTH_USERNAME_TOOLONG: stringId = IDS_ERR_USERNAME_TOOLONG; break;
case AUTH_USERNAME_BADFORMAT: stringId = IDS_ERR_USERNAME_BADFORMAT; break;
case AUTH_PASSWORD_EMPTY: stringId = IDS_ERR_PASSWORD_EMPTY; break;
case AUTH_PASSWORD_TOOSHORT: stringId = IDS_ERR_PASSWORD_TOOSHORT; break;
case AUTH_PASSWORD_TOOLONG: stringId = IDS_ERR_PASSWORD_TOOLONG; break;
case AUTH_PASSWORD_BADFORMAT: stringId = IDS_ERR_PASSWORD_BADFORMAT; break;
case AUTH_PASSCODE_EMPTY: stringId = IDS_ERR_PASSCODE_EMPTY; break;
case AUTH_PASSCODE_TOOSHORT: stringId = IDS_ERR_PASSCODE_TOOSHORT; break;
case AUTH_PASSCODE_TOOLONG: stringId = IDS_ERR_PASSCODE_TOOLONG; break;
case AUTH_PASSCODE_BADFORMAT: stringId = IDS_ERR_PASSCODE_BADFORMAT; break;
default: stringId = IDS_ERR_UNKNOWN; break;
}
WCHAR szBuffer[2048] = {0};
LPWSTR cursor = szBuffer;
size_t remaining = ARRAYSIZE(szBuffer);
WASABI_API_LNGSTRINGW_BUF(IDS_LOGIN_FAILURE, cursor, remaining);
size_t len = lstrlen(cursor);
cursor += len;
remaining -= len;
if (cursor != szBuffer)
StringCchCopyEx(cursor, remaining, L": ", &cursor, &remaining, 0);
WASABI_API_LNGSTRINGW_BUF(stringId, cursor, remaining);
notifier->text = LoginBox_CopyString(szBuffer);
if (NULL == notifier->text)
resultCode = FALSE;
}
else
{
notifier->text = LoginBox_CopyString(pszText);
if (NULL == notifier->text)
resultCode = FALSE;
}
}
if (FALSE != fInvalidate)
InvalidateRect(hwnd, NULL, TRUE);
return resultCode;
}
static LRESULT LoginNotifier_OnCreate(HWND hwnd, CREATESTRUCT* pcs)
{
LOGINNOTIFIER *notifier = (LOGINNOTIFIER*)calloc(1, sizeof(LOGINNOTIFIER));
if (NULL != notifier)
{
SetLastError(ERROR_SUCCESS);
if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)notifier) && ERROR_SUCCESS != GetLastError())
{
free(notifier);
notifier = NULL;
}
}
if (NULL == notifier)
return -1;
notifier->textHeight = -1;
notifier->rgbBack = RGB(247, 247, 247);
notifier->rgbText = RGB(0, 0, 0);
return 0;
}
static void LoginNotifier_OnDestroy(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
SetWindowLongPtr(hwnd, 0, 0L);
if (NULL == notifier) return;
if (NULL != notifier->image)
DeleteObject(notifier->image);
free(notifier);
}
static void LoginNotifier_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp)
{
if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
return;
LoginNotifier_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags));
}
static void LoginNotifier_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
if (BeginPaint(hwnd, &ps))
{
if (ps.rcPaint.left != ps.rcPaint.right)
LoginNotifier_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
EndPaint(hwnd, &ps);
}
}
static void LoginNotifier_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
{
RECT clientRect;
if (GetClientRect(hwnd, &clientRect))
LoginNotifier_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options));
}
static void LoginNotifier_OnSetFont(HWND hwnd, HFONT hFont, BOOL fRedraw)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
notifier->font = hFont;
notifier->textHeight = -1;
if (NULL != fRedraw)
InvalidateRect(hwnd, NULL, FALSE);
}
static LRESULT LoginNotifier_OnGetFont(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
return (NULL != notifier) ? (LRESULT)notifier->font : NULL;
}
static LRESULT LoginNotifier_OnSetText(HWND hwnd, LPCWSTR pszText)
{
return LoginNotifier_SetNotification(hwnd, NLNTYPE_INFORMATION, pszText, TRUE);
}
static LRESULT LoginNotifier_OnGetText(HWND hwnd, LPWSTR pszBuffer, size_t cchBufferMax)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
LPCWSTR pszText = (NULL != notifier) ? notifier->text : NULL;
if (NULL == pszBuffer)
return 0;
size_t remaining;
StringCchCopyEx(pszBuffer, cchBufferMax, pszText, NULL, &remaining, STRSAFE_IGNORE_NULLS);
return (cchBufferMax - remaining);
}
static LRESULT LoginNotifier_OnGetTextLength(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
return (NULL != notifier && NULL != notifier->text) ? lstrlen(notifier->text) : 0;
}
static LRESULT LoginNotifier_OnNotify(HWND hwnd, INT type, LPCWSTR pszText)
{
return LoginNotifier_SetNotification(hwnd, type, pszText, TRUE);
}
static LRESULT LoginNotifier_OnGetIdealHeight(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return 0;
if (-1 == notifier->textHeight)
notifier->textHeight = LoginNotifier_CalcTextHeight(hwnd, NULL, &notifier->aveCharWidth);
INT iconHeight(0);
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
loginGui->GetIconDimensions(NULL, &iconHeight);
loginGui->Release();
}
INT height = (notifier->textHeight > iconHeight) ?
notifier->textHeight : iconHeight;
height += SPACING_TOP + SPACING_BOTTOM;
return height;
}
static LRESULT LoginNotifier_OnGetIdealSize(HWND hwnd, SIZE *sizeOut)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier || NULL == sizeOut) return FALSE;
if (-1 == notifier->textHeight)
notifier->textHeight = LoginNotifier_CalcTextHeight(hwnd, NULL, &notifier->aveCharWidth);
INT iconWidth(0), iconHeight(0);
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
loginGui->GetIconDimensions(&iconWidth, &iconHeight);
loginGui->Release();
}
sizeOut->cy = (notifier->textHeight > iconHeight) ?
notifier->textHeight :
iconHeight;
sizeOut->cy += SPACING_TOP + SPACING_BOTTOM;
sizeOut->cx = (0 != iconWidth) ?
(GRADIENT_LEFT + GRADIENT_RIGHT + iconWidth) :
0;
INT cchText = (NULL != notifier->text) ? lstrlen(notifier->text) : 0;
BOOL resultOk = TRUE;
if (0 != cchText)
{
sizeOut->cx += notifier->aveCharWidth+2;
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT fontOrig = (HFONT)SelectObject(hdc, notifier->font);
SIZE textSize;
if (FALSE != GetTextExtentPoint32W(hdc, notifier->text, cchText, &textSize))
sizeOut->cx += textSize.cx;
else
resultOk = FALSE;
SelectObject(hdc, fontOrig);
ReleaseDC(hwnd, hdc);
}
else
resultOk = FALSE;
}
return resultOk;
}
static void LoginNotifier_OnSetBkColor(HWND hwnd, COLORREF rgbColor)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
notifier->rgbBack = rgbColor;
}
static LRESULT LoginNotifier_OnGetBkColor(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return RGB(255, 0, 255);
return notifier->rgbBack;
}
static void LoginNotifier_OnSetTextColor(HWND hwnd, COLORREF rgbColor)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
notifier->rgbText = rgbColor;
}
static LRESULT LoginNotifier_OnGetTextColor(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return RGB(255, 0, 255);
return notifier->rgbText;
}
static void LoginNotifier_OnPlayBeep(HWND hwnd)
{
LOGINNOTIFIER *notifier = GetNotifier(hwnd);
if (NULL == notifier) return;
UINT beepType;
switch(notifier->type)
{
case NLNTYPE_INFORMATION: beepType = MB_ICONASTERISK; break;
case NLNTYPE_WARNING: beepType = MB_ICONEXCLAMATION; break;
case NLNTYPE_ERROR: beepType = MB_ICONHAND; break;
case NLNTYPE_QUESTION: beepType = MB_ICONQUESTION; break;
default: return;
}
LoginBox_MessageBeep(beepType);
}
static LRESULT WINAPI LoginNotifier_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: return LoginNotifier_OnCreate(hwnd, (CREATESTRUCT*)lParam);
case WM_DESTROY: LoginNotifier_OnDestroy(hwnd); return 0;
case WM_ERASEBKGND: return 0;
case WM_PAINT: LoginNotifier_OnPaint(hwnd); return 0;
case WM_PRINTCLIENT: LoginNotifier_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0;
case WM_PRINT: return 0;
case WM_WINDOWPOSCHANGED: LoginNotifier_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
case WM_SIZE: return 0;
case WM_SETFONT: LoginNotifier_OnSetFont(hwnd, (HFONT)wParam, (BOOL)LOWORD(lParam)); return 0;
case WM_GETFONT: return LoginNotifier_OnGetFont(hwnd);
case WM_SETTEXT: return LoginNotifier_OnSetText(hwnd, (LPCWSTR)lParam);
case WM_GETTEXT: return LoginNotifier_OnGetText(hwnd, (LPWSTR)lParam, (INT)wParam);
case WM_GETTEXTLENGTH: return LoginNotifier_OnGetTextLength(hwnd);
case NLNM_NOTIFY: return LoginNotifier_OnNotify(hwnd, (INT)wParam, (LPCWSTR)lParam);
case NLNM_GETIDEALHEIGHT: return LoginNotifier_OnGetIdealHeight(hwnd);
case NLNM_SETBKCOLOR: LoginNotifier_OnSetBkColor(hwnd, (COLORREF)lParam); return 0;
case NLNM_GETBKCOLOR: return LoginNotifier_OnGetBkColor(hwnd);
case NLNM_SETTEXTCOLOR: LoginNotifier_OnSetTextColor(hwnd, (COLORREF)lParam); return 0;
case NLNM_GETTEXTCOLOR: return LoginNotifier_OnGetTextColor(hwnd);
case NLNM_PLAYBEEP: LoginNotifier_OnPlayBeep(hwnd); return 0;
case NLNM_GETIDEALSIZE: return LoginNotifier_OnGetIdealSize(hwnd, (SIZE*)lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,54 @@
#ifndef NULLSOFT_AUTH_LOGIN_NOTIFIER_HEADER
#define NULLSOFT_AUTH_LOGIN_NOTIFIER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginGuiObject;
HWND LoginNotifier_CreateWindow(UINT styleEx, UINT style, INT x, INT y, INT cx, INT cy, HWND hParent, INT controlId);
#define NLNTYPE_INFORMATION 0
#define NLNTYPE_WARNING 1
#define NLNTYPE_ERROR 2
#define NLNTYPE_QUESTION 3
#define NLNM_FIRST (WM_USER + 10)
#define NLNM_NOTIFY (NLNM_FIRST + 0) // wParam = (WPARAM)(INT)notificationType, lParam = (LPARAM)(LPCWSTR)notificationText; Return - TRUE on success; notificationText can be MAKEINTRESOURCE(authError)
#define LoginNotifier_Notify(/*HWND*/ __hwnd, /*INT*/ __notificationType, /*LPCWSTR*/ __notificationText)\
(SNDMSG((__hwnd), NLNM_NOTIFY, (WPARAM)(__notificationType), (LPARAM)(__notificationText)))
#define NLNM_GETIDEALHEIGHT (NLNM_FIRST + 1) // wParam - not used, lParam - not used; Return - ideal height
#define LoginNotifier_GetIdealHeight(/*HWND*/ __hwnd)\
((INT)SNDMSG((__hwnd), NLNM_GETIDEALHEIGHT, 0, 0L))
#define NLNM_SETBKCOLOR (NLNM_FIRST + 2) // wParam - not used, lParam = (LPARAM)(COLORREF)rgb; Return ignored
#define LoginNotifier_SetBkColor(/*HWND*/ __hwnd, /*COLORREF*/ __rgb)\
(SNDMSG((__hwnd), NLNM_SETBKCOLOR, 0, (LPARAM)(__rgb)))
#define NLNM_GETBKCOLOR (NLNM_FIRST + 3) // wParam - not used, lParam - not used; Return back color
#define LoginNotifier_GetBkColor(/*HWND*/ __hwnd)\
((COLORREF)SNDMSG((__hwnd), NLNM_GETBKCOLOR, 0, 0L))
#define NLNM_SETTEXTCOLOR (NLNM_FIRST + 4) // wParam - not used, lParam = (LPARAM)(COLORREF)rgb; Return ignored
#define LoginNotifier_SetTextColor(/*HWND*/ __hwnd, /*COLORREF*/ __rgb)\
(SNDMSG((__hwnd), NLNM_SETTEXTCOLOR, 0, (LPARAM)(__rgb)))
#define NLNM_GETTEXTCOLOR (NLNM_FIRST + 5) // wParam - not used, lParam - not used; Return back color
#define LoginNotifier_GetTextColor(/*HWND*/ __hwnd)\
((COLORREF)SNDMSG((__hwnd), NLNM_GETTEXTCOLOR, 0, 0L))
#define NLNM_PLAYBEEP (NLNM_FIRST + 6) // wParam - not used, lParam - not used; Return ignored
#define LoginNotifier_PlayBeep(/*HWND*/ __hwnd)\
(SNDMSG((__hwnd), NLNM_PLAYBEEP, 0, 0L))
#define NLNM_GETIDEALSIZE (NLNM_FIRST + 7) // wParam - not used, lParam - (LPARAM)(SIZE*)sizeOut; Return TRUE on success
#define LoginNotifier_GetIdealSize(/*HWND*/ __hwnd, /*SIZE* */ __sizeOut)\
((BOOL)SNDMSG((__hwnd), NLNM_GETIDEALSIZE, 0, (LPARAM)(__sizeOut)))
#endif //NULLSOFT_AUTH_LOGIN_NOTIFIER_HEADER

View File

@@ -0,0 +1,624 @@
#define OEMRESOURCE
#include "./loginPage.h"
#include "./loginData.h"
#include "./loginBox.h"
#include "./loginProvider.h"
#include "./loginGui.h"
#include "./common.h"
#include "../api.h"
#include "../../nu/windowsTheme.h"
#include <vssym32.h>
#include <vsstyle.h>
#include <windows.h>
#define IDC_TITLE 9999
#define IDC_HELPLINK 9998
typedef struct __LOGINPAGECREATEPARAM
{
LOGINPAGECREATOR fnCreator;
LPARAM lParam;
HWND hLoginbox;
} LOGINPAGECREATEPARAM;
LoginPage::LoginPage(HWND hwnd, HWND hLoginbox)
{
this->hwnd = hwnd;
this->hLoginbox = hLoginbox;
}
LoginPage::~LoginPage()
{
}
HWND LoginPage::CreatePage(HWND hLoginbox, LPCWSTR pszTemplate, HWND hParent, LPARAM param, LOGINPAGECREATOR fnCreator)
{
if (NULL == hLoginbox || NULL == hParent)
return NULL;
if (NULL == pszTemplate || NULL == fnCreator)
return NULL;
LOGINPAGECREATEPARAM createParam;
createParam.fnCreator = fnCreator;
createParam.lParam = param;
createParam.hLoginbox = hLoginbox;
return WASABI_API_CREATEDIALOGPARAMW((INT)(INT_PTR)pszTemplate, hParent, LoginPage_DialogProc, (LPARAM)&createParam);
}
void LoginPage::UpdateColors()
{
rgbTitle = RGB(0, 51, 153);
rgbSecondaryText = GetSysColor(COLOR_WINDOWTEXT);
rgbText = GetSysColor(COLOR_WINDOWTEXT);
rgbBack = GetSysColor(COLOR_WINDOW);
hbrBack = GetSysColorBrush(COLOR_WINDOW);
if (SUCCEEDED(UxTheme_LoadLibrary()) && FALSE != UxIsAppThemed())
{
UXTHEME hTheme = UxOpenThemeData(hwnd, L"TEXTSTYLE");
if (NULL != hTheme)
{
UxGetThemeColor(hTheme, TEXT_MAININSTRUCTION, 0, TMT_TEXTCOLOR, &rgbTitle);
UxGetThemeColor(hTheme, TEXT_BODYTEXT, 0, TMT_TEXTCOLOR, &rgbText);
UxGetThemeColor(hTheme, TEXT_SECONDARYTEXT, 0, TMT_TEXTCOLOR, &rgbSecondaryText);
UxCloseThemeData(hTheme);
}
}
}
void LoginPage::UpdateMargins()
{
SetRect(&margins, 14, 7, 7, 7);
MapDialogRect(hwnd, &margins);
RECT controlRect;
HWND hControl = GetDlgItem(hwnd, IDC_HELPLINK);
if (NULL != hControl && GetWindowRect(hControl, &controlRect))
{
INT t = (controlRect.right - controlRect.left) + 1;
if (margins.right < t) margins.right = t;
t = (controlRect.bottom - controlRect.top) + 1;
if (margins.top < t) margins.top = t;
}
}
static HBITMAP LoginPage_GetHelpBitmap(HWND hwnd, HBRUSH hbrBack, INT *pWidth, INT *pHeight)
{
LoginGuiObject *loginGui;
if (FAILED(LoginGuiObject::QueryInstance(&loginGui)))
return NULL;
RECT rectSrc;
HBITMAP hbmpSrc = loginGui->GetIcon(LoginGuiObject::iconQuestion, &rectSrc);
HBITMAP hbmpDst = NULL;
if (NULL != hbmpSrc)
{
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if( NULL != hdc)
{
HDC hdcDst = CreateCompatibleDC(hdc);
HDC hdcSrc = CreateCompatibleDC(hdc);
if (NULL != hdcDst && NULL != hdcSrc)
{
INT imageWidth = rectSrc.right - rectSrc.left;
INT imageHeight = rectSrc.bottom - rectSrc.top;
BITMAPINFOHEADER header;
ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
header.biSize = sizeof(BITMAPINFOHEADER);
header.biCompression = BI_RGB;
header.biBitCount = 24;
header.biPlanes = 1;
header.biWidth = imageWidth;
header.biHeight = -imageHeight;
void *pixelData;
hbmpDst = CreateDIBSection(hdc, (LPBITMAPINFO)&header, DIB_RGB_COLORS, (void**)&pixelData, NULL, 0);
if (NULL != hbmpDst)
{
HBITMAP hbmpDstOrig = (HBITMAP)SelectObject(hdcDst, hbmpDst);
HBITMAP hbmpSrcOrig = (HBITMAP)SelectObject(hdcSrc, hbmpSrc);
RECT fillRect;
SetRect(&fillRect, 0, 0, imageWidth, imageHeight);
FillRect(hdcDst, &fillRect, hbrBack);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
GdiAlphaBlend(hdcDst, 0, 0, imageWidth, imageHeight,
hdcSrc, rectSrc.left, rectSrc.top, imageWidth, imageHeight, bf);
SelectObject(hdcDst, hbmpDstOrig);
SelectObject(hdcSrc, hbmpSrcOrig);
if (NULL != pWidth) *pWidth = imageWidth;
if (NULL != pHeight) *pHeight = imageHeight;
}
}
if (NULL != hdcDst) DeleteDC(hdcDst);
if (NULL != hdcSrc) DeleteDC(hdcSrc);
ReleaseDC(hwnd, hdc);
}
}
loginGui->Release();
return hbmpDst;
}
void LoginPage::UpdateLayout(BOOL fRedraw)
{
RECT clientRect;
GetClientRect(hwnd, &clientRect);
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
const INT szControls[] = { IDC_HELPLINK, IDC_TITLE};
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
RECT rect;
INT cx, cy, x, y;
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
HWND hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &rect)) continue;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
x = rect.left;
y = rect.top;
cx = rect.right - rect.left;
cy = rect.bottom - rect.top;
switch(szControls[i])
{
case IDC_HELPLINK:
x = clientRect.right - cx - 1;
if (x < clientRect.left + 1) x = clientRect.left + 1;
y = clientRect.top + 1;
break;
case IDC_TITLE:
x = clientRect.left + margins.left;
y = clientRect.top + margins.top;
cx = clientRect.right - margins.right - x;
cy = 0;
LoginBox_GetWindowTextSize(hControl, cx, &cx, &cy);
if ((cx + x) > (clientRect.right - margins.right))
cx = clientRect.right - margins.right - x;
if ((cy + y) > (clientRect.bottom - margins.bottom))
cy = clientRect.bottom - margins.bottom - y;
break;
}
hdwp = DeferWindowPos(hdwp, hControl, NULL, x, y, cx, cy, flags);
if (NULL == hdwp) break;
}
if (NULL != hdwp)
EndDeferWindowPos(hdwp);
}
BOOL LoginPage::GetPageRect(RECT *prc)
{
if (NULL == prc || FALSE == GetClientRect(hwnd, prc))
return FALSE;
prc->left += margins.left;
prc->top += margins.top;
prc->right -= margins.right;
prc->bottom -= margins.bottom;
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
if (NULL != hTitle)
{
UINT titleStyle = GetWindowStyle(hTitle);
if (0 != (WS_VISIBLE & titleStyle))
{
RECT titleRect;
if (FALSE != GetWindowRect(hTitle, &titleRect))
{
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&titleRect, 2);
titleRect.bottom += GetTitleSpacing();
if (titleRect.bottom > prc->top)
{
prc->top = titleRect.bottom;
if (prc->top > prc->bottom)
prc->top = prc->bottom;
}
}
}
}
return TRUE;
}
INT LoginPage::GetTitleSpacing()
{
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
if (NULL == hTitle) return 0;
HFONT fontTitle = (HFONT)SendMessage(hTitle, WM_GETFONT, 0, 0L);
HDC hdc = GetDCEx(hTitle, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL == hdc) return 0;
HFONT fontOrig = (HFONT)SelectObject(hdc, fontTitle);
TEXTMETRIC tm;
if (FALSE == GetTextMetrics(hdc, &tm))
tm.tmHeight = 0;
SelectObject(hdc, fontOrig);
ReleaseDC(hTitle, hdc);
return tm.tmHeight;
}
BOOL LoginPage::IsHelpAvailable()
{
LoginProvider *provider;
if (NULL == hLoginbox ||
FALSE == LoginBox_GetActiveProvider(hLoginbox, &provider) ||
NULL == provider)
{
return FALSE;
}
WCHAR szBuffer[8192] = {0};
HRESULT hr = provider->GetHelpLink(szBuffer, ARRAYSIZE(szBuffer));
provider->Release();
if (FAILED(hr) || L'\0' == szBuffer[0])
return FALSE;
return TRUE;
}
BOOL LoginPage::ShowHelp()
{
LoginProvider *provider;
if (NULL == hLoginbox ||
FALSE == LoginBox_GetActiveProvider(hLoginbox, &provider) ||
NULL == provider)
{
return FALSE;
}
WCHAR szBuffer[8192] = {0};
HRESULT hr = provider->GetHelpLink(szBuffer, ARRAYSIZE(szBuffer));
provider->Release();
if (FAILED(hr) || L'\0' == szBuffer[0])
return FALSE;
return LoginBox_OpenUrl(hwnd, szBuffer, TRUE);
}
BOOL LoginPage::SetLabelText(INT controlId, LPCWSTR pszText)
{
HWND hLabel = GetDlgItem(hwnd, controlId);
if (NULL == hLabel) return FALSE;
LPWSTR pszTemp = NULL;
if (NULL != pszText && L'\0' != *pszText)
{
INT cchLabel = lstrlenW(pszText);
if (cchLabel > 0 && L':' != pszText[cchLabel-1])
{
pszTemp = LoginBox_MallocString(cchLabel + 2);
if (NULL != pszTemp)
{
CopyMemory(pszTemp, pszText, sizeof(WCHAR) * cchLabel);
pszTemp[cchLabel] = L':';
pszTemp[cchLabel + 1] = L'\0';
pszText = pszTemp;
}
}
}
BOOL result = SetWindowText(hLabel, pszText);
if (NULL != pszTemp)
LoginBox_FreeString(pszTemp);
return result;
}
BOOL LoginPage::OnInitDialog(HWND hFocus, LPARAM param)
{
HWND hControl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 100, 24, hwnd, (HMENU)IDC_TITLE, NULL, 0L);
if (NULL != hControl)
{
HFONT fontTitle = NULL;
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
fontTitle = loginGui->GetTitleFont();
loginGui->Release();
}
if (NULL == fontTitle)
fontTitle = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
if (NULL != fontTitle)
SNDMSG(hControl, WM_SETFONT, (WPARAM)fontTitle, 0L);
}
INT imageWidth, imageHeight;
HBITMAP bitmapHelp = LoginPage_GetHelpBitmap(hwnd, hbrBack, &imageWidth, &imageHeight);
if (NULL != bitmapHelp)
{
UINT controlStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
SS_BITMAP | SS_NOTIFY;
if (FALSE != IsHelpAvailable())
controlStyle |= WS_VISIBLE;
hControl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", NULL, controlStyle,
0, 0, 0, 0, hwnd, (HMENU)IDC_HELPLINK, NULL, 0L);
HBITMAP bitmapSelected = NULL;
if (NULL != hControl)
{
bitmapSelected = (HBITMAP)SNDMSG(hControl, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)bitmapHelp);
if (NULL != bitmapSelected)
DeleteObject(bitmapSelected);
bitmapSelected = (HBITMAP)SNDMSG(hControl, STM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0L);
}
if (bitmapSelected != bitmapHelp)
DeleteObject(bitmapHelp);
}
UpdateMargins();
UpdateColors();
UpdateLayout(FALSE);
PostMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0L);
return FALSE;
}
void LoginPage::OnDestroy()
{
HWND hControl = GetDlgItem(hwnd, IDC_HELPLINK);
if (NULL != hControl)
{
HBITMAP bitmapSelected = (HBITMAP)SNDMSG(hControl, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, 0L);
if (NULL != bitmapSelected)
DeleteObject(bitmapSelected);
}
}
void LoginPage::OnWindowPosChanged(const WINDOWPOS *pwp)
{
if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
UpdateLayout(0 == (SWP_NOREDRAW & pwp->flags));
}
void LoginPage::OnCommand(UINT commandId, UINT eventType, HWND hControl)
{
switch(commandId)
{
case IDC_HELPLINK:
switch(eventType)
{
case STN_CLICKED:
ShowHelp();
break;
}
break;
}
}
BOOL LoginPage::OnNotify(UINT controlId, const NMHDR *pnmh)
{
return FALSE;
}
BOOL LoginPage::OnGetLoginData(LoginData **ppLoginData)
{
if (FAILED(LoginData::CreateInstance(NULL, hwnd, hLoginbox, ppLoginData)))
return FALSE;
return TRUE;
}
void LoginPage::OnUpdateStateChange(BOOL updateActive)
{
}
BOOL LoginPage::OnSetUsername(LPCWSTR pszUsername)
{
return FALSE;
}
BOOL LoginPage::OnSetPassword(LPCWSTR pszPassword)
{
return FALSE;
}
HWND LoginPage::OnGetFirstItem()
{
return NULL;
}
BOOL LoginPage::OnSetTitle(LPCWSTR pszTitle)
{
HWND hControl = GetDlgItem(hwnd, IDC_TITLE);
if (NULL == hControl) return FALSE;
BOOL result = (BOOL)SNDMSG(hControl, WM_SETTEXT, 0, (LPARAM)pszTitle);
if (FALSE != result)
UpdateLayout(TRUE);
return result;
}
HBRUSH LoginPage::OnGetStaticColor(HDC hdc, HWND hControl)
{
INT controlId = (INT)GetWindowLongPtr(hControl, GWLP_ID);
switch(controlId)
{
case IDC_TITLE:
SetTextColor(hdc, rgbTitle);
break;
default:
SetTextColor(hdc, rgbText);
break;
}
SetBkColor(hdc, rgbBack);
return hbrBack;
}
HBRUSH LoginPage::OnGetDialogColor(HDC hdc, HWND hControl)
{
SetTextColor(hdc, rgbText);
SetBkColor(hdc, rgbBack);
return hbrBack;
}
BOOL LoginPage::OnSetCursor(HWND hTarget, INT hitCode, INT uMsg)
{
HWND hControl = GetDlgItem(hwnd, IDC_HELPLINK);
if (hControl == hTarget && NULL != hControl)
{
UINT controlStyle = GetWindowStyle(hControl);
if (WS_VISIBLE == ((WS_VISIBLE | WS_DISABLED) & controlStyle))
{
HCURSOR hCursor = LoadCursor(NULL, IDC_HAND);
if (NULL != hCursor)
{
SetCursor(hCursor);
return TRUE;
}
}
}
return FALSE;
}
BOOL LoginPage::OnHelp(HELPINFO *phi)
{
return ShowHelp();
}
void LoginPage::OnThemeChanged()
{
UpdateColors();
}
void LoginPage::OnSysColorChanged()
{
UpdateColors();
}
INT_PTR LoginPage::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
case WM_DESTROY: OnDestroy(); return TRUE;
case WM_NOTIFY: MSGRESULT(hwnd, OnNotify((INT)wParam, (NMHDR*)lParam));
case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
case WM_WINDOWPOSCHANGED: OnWindowPosChanged((WINDOWPOS*)lParam); return TRUE;
case WM_SIZE: return TRUE;
case WM_CTLCOLORSTATIC: return (INT_PTR)OnGetStaticColor((HDC)wParam, (HWND)lParam);
case WM_CTLCOLORDLG: return (INT_PTR)OnGetDialogColor((HDC)wParam, (HWND)lParam);
case WM_SETCURSOR:
if (FALSE != OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam)))
MSGRESULT(hwnd, TRUE);
break;
case WM_HELP:
if (FALSE != OnHelp((HELPINFO*)lParam))
MSGRESULT(hwnd, TRUE);
break;
case WM_THEMECHANGED: OnThemeChanged(); return TRUE;
case WM_SYSCOLORCHANGE: OnSysColorChanged(); return TRUE;
case NLPM_GETLOGINDATA: MSGRESULT(hwnd, OnGetLoginData((LoginData**)lParam));
case NLPM_UPDATESTATECHANGE: OnUpdateStateChange((BOOL)lParam); return TRUE;
case NLPM_SETUSERNAME: MSGRESULT(hwnd, OnSetUsername((LPCWSTR)lParam));
case NLPM_SETPASSWORD: MSGRESULT(hwnd, OnSetPassword((LPCWSTR)lParam));
case NLPM_GETFIRSTITEM: MSGRESULT(hwnd, OnGetFirstItem());
case NLPM_SETTITLE: MSGRESULT(hwnd, OnSetTitle((LPCWSTR)lParam));
}
return FALSE;
}
static INT_PTR CALLBACK LoginPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static ATOM LOGINPAGE_PROP = 0;
LoginPage *page = (LoginPage*)GetProp(hwnd, MAKEINTATOM(LOGINPAGE_PROP));
if (NULL == page)
{
switch(uMsg)
{
case WM_INITDIALOG:
if (0 == LOGINPAGE_PROP)
{
LOGINPAGE_PROP = GlobalAddAtomW(L"NullsoftLoginPageProp");
if (0 == LOGINPAGE_PROP)
return 0;
}
if (NULL != lParam)
{
LOGINPAGECREATEPARAM *create = (LOGINPAGECREATEPARAM*)lParam;
lParam = create->lParam;
if (SUCCEEDED(create->fnCreator(hwnd, create->hLoginbox, &page)))
{
if (FALSE == SetProp(hwnd, MAKEINTATOM(LOGINPAGE_PROP), (HANDLE)page))
{
delete(page);
page = NULL;
}
}
}
if (NULL != page)
return page->DialogProc(uMsg, wParam, lParam);
break;
}
return 0;
}
INT_PTR result = page->DialogProc(uMsg, wParam, lParam);
if (WM_DESTROY == uMsg)
{
RemoveProp(hwnd, MAKEINTATOM(LOGINPAGE_PROP));
delete(page);
}
return result;
}

View File

@@ -0,0 +1,733 @@
#include "./loginPopup.h"
#include "../api.h"
#include "../../nu/Vectors.h"
#include "./loginNotifier.h"
#include "./common.h"
typedef Vector<HWND> WindowList;
typedef struct __THREADPOPUPDATA
{
HHOOK hHook;
WindowList windowList;
} THREADPOPUPDATA;
static size_t threadStorage = TLS_OUT_OF_INDEXES;
typedef struct __LOGINPOPUPCREATEPARAM
{
LoginPopup::Creator fnCreator;
LPARAM lParam;
} LOGINPOPUPCREATEPARAM;
#define IDC_NOTIFIER 10001
//#define COLOR_TITLE COLOR_3DLIGHT
//#define COLOR_TITLETEXT COLOR_WINDOWTEXT
#define COLOR_CLIENT COLOR_3DFACE
#define COLOR_CLIENTTEXT COLOR_WINDOWTEXT
LoginPopup::LoginPopup(HWND hwnd, UINT popupType, LPCWSTR pszTitle)
: alertType(-1), alertMessage(NULL)
{
buttonHeight = buttonSpace = 0;
this->hwnd = hwnd;
if (NULL != pszTitle)
SetTitle(popupType, pszTitle);
}
LoginPopup::~LoginPopup()
{
RegisterPopup(hwnd, FALSE);
if (FALSE == IS_INTRESOURCE(alertMessage))
LoginBox_FreeString(alertMessage);
}
HWND LoginPopup::CreatePopup(LPCWSTR pszTemplate, HWND hParent, LPARAM param, Creator fnCreator)
{
if (NULL == hParent || NULL == pszTemplate || NULL == fnCreator)
return NULL;
LOGINPOPUPCREATEPARAM createParam;
createParam.fnCreator = fnCreator;
createParam.lParam = param;
return WASABI_API_CREATEDIALOGPARAMW((INT)(INT_PTR)pszTemplate, hParent, LoginPopup_DialogProc, (LPARAM)&createParam);
}
BOOL LoginPopup::RegisterPopup(HWND hwnd, BOOL fRegister)
{
if (NULL == hwnd || GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId())
return FALSE;
THREADPOPUPDATA *data = NULL;
if (TLS_OUT_OF_INDEXES == threadStorage)
{
if (NULL == WASABI_API_APP)
return FALSE;
threadStorage = WASABI_API_APP->AllocateThreadStorage();
if (TLS_OUT_OF_INDEXES == threadStorage)
return FALSE;
}
else
{
data = (THREADPOPUPDATA*)WASABI_API_APP->GetThreadStorage(threadStorage);
}
if (NULL == data)
{
data = new THREADPOPUPDATA();
if (NULL == data) return FALSE;
data->hHook = SetWindowsHookEx(WH_MSGFILTER, LoginPopup_MessageFilter, NULL, GetCurrentThreadId());
if (NULL == data->hHook)
{
delete data;
return FALSE;
}
WASABI_API_APP->SetThreadStorage(threadStorage, data);
}
size_t index = data->windowList.size();
while(index--)
{
if (hwnd == data->windowList[index])
{
if (FALSE == fRegister)
{
data->windowList.eraseAt(index);
if (0 == data->windowList.size())
{
if (NULL != data->hHook)
UnhookWindowsHookEx(data->hHook);
WASABI_API_APP->SetThreadStorage(threadStorage, NULL);
delete data;
}
}
return TRUE;
}
}
if (FALSE != fRegister)
{
data->windowList.push_back(hwnd);
return TRUE;
}
return FALSE;
}
BOOL LoginPopup::EnumeratePopups(HWND hHost, Enumerator callback, LPARAM param)
{
if (NULL == callback ||
NULL == hHost || GetWindowThreadProcessId(hHost, NULL) != GetCurrentThreadId())
return FALSE;
THREADPOPUPDATA *data = (TLS_OUT_OF_INDEXES != threadStorage && NULL != WASABI_API_APP) ?
(THREADPOPUPDATA *)WASABI_API_APP->GetThreadStorage(threadStorage) : NULL;
if (NULL == data)
return FALSE;
size_t index = data->windowList.size();
while(index--)
{
HWND hPopup = data->windowList[index];
if (IsChild(hHost, hPopup) && FALSE == callback(hPopup, param))
return FALSE;
}
return TRUE;
}
BOOL LoginPopup::AnyPopup(HWND hHost)
{
if (NULL == hHost || GetWindowThreadProcessId(hHost, NULL) != GetCurrentThreadId())
return FALSE;
THREADPOPUPDATA *data = (TLS_OUT_OF_INDEXES != threadStorage && NULL != WASABI_API_APP) ?
(THREADPOPUPDATA *)WASABI_API_APP->GetThreadStorage(threadStorage) : NULL;
if (NULL == data)
return FALSE;
size_t index = data->windowList.size();
while(index--)
{
if (IsChild(hHost, data->windowList[index]))
return TRUE;
}
return FALSE;
}
void LoginPopup::UpdateLayout(BOOL fRedraw)
{
RECT rect;
GetClientRect(hwnd, &rect);
HWND hNotifier;
hNotifier = GetDlgItem(hwnd, IDC_NOTIFIER);
if (NULL != hNotifier)
{
INT height = LoginNotifier_GetIdealHeight(hNotifier);
SetWindowPos(hNotifier, NULL, rect.left, rect.top, rect.right - rect.left, height,
SWP_NOACTIVATE | SWP_NOZORDER);
}
}
void LoginPopup::Paint(HDC hdc, const RECT *prcPaint, BOOL fErase)
{
if (FALSE != fErase)
{
RECT clientRect;
GetClientRect(hwnd, &clientRect);
COLORREF rgbOrig, rgbPart;
rgbOrig = GetBkColor(hdc);
if (buttonHeight > 0)
{
RECT buttonRect;
SetRect(&buttonRect,
clientRect.left, clientRect.bottom - (2* clientMargins.bottom + buttonHeight),
clientRect.right, clientRect.bottom);
clientRect.bottom = buttonRect.top;
buttonRect.top++;
rgbPart = GetSysColor(COLOR_3DFACE);
SetBkColor(hdc, rgbPart);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &buttonRect, NULL, 0, NULL);
buttonRect.bottom = buttonRect.top;
buttonRect.top--;
rgbPart = GetSysColor(COLOR_3DLIGHT);
SetBkColor(hdc, rgbPart);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &buttonRect, NULL, 0, NULL);
}
rgbPart = GetSysColor(COLOR_CLIENT);
SetBkColor(hdc, rgbPart);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &clientRect, NULL, 0, NULL);
SetBkColor(hdc, rgbOrig);
}
}
void LoginPopup::EndDialog(INT_PTR code)
{
DestroyWindow(hwnd);
}
void LoginPopup::UpdateMargins()
{
SetRect(&clientMargins, 8, 6, 8, 6);
MapDialogRect(hwnd, &clientMargins);
SetRect(&infoMargins, 6, 8, 6, 8);
MapDialogRect(hwnd, &infoMargins);
RECT rect;
SetRect(&rect, 4, 15, 0, 0);
MapDialogRect(hwnd, &rect);
buttonHeight = rect.top;
buttonSpace = rect.left;
}
void LoginPopup::SetTitle(UINT type, LPCWSTR title)
{
popupType = type;
if (NULL == title || FALSE == IS_INTRESOURCE(title))
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)title);
else
{
WCHAR szBuffer[256] = {0};
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)title, szBuffer, ARRAYSIZE(szBuffer));
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)szBuffer);
}
}
void LoginPopup::UpdateTitle(BOOL playBeep)
{
HWND hNotifier;
hNotifier = GetDlgItem(hwnd, IDC_NOTIFIER);
if (NULL == hNotifier) return;
WCHAR szBuffer[512] = {0};
LPCWSTR text;
UINT type;
if (-1 != alertType && NULL != alertMessage)
{
type = alertType;
text = (IS_INTRESOURCE(alertMessage)) ?
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)alertMessage, szBuffer, ARRAYSIZE(szBuffer)) :
alertMessage;
}
else
{
type = popupType;
SendMessage(hwnd, WM_GETTEXT, (WPARAM)ARRAYSIZE(szBuffer), (LPARAM)szBuffer);
text = szBuffer;
}
LoginNotifier_Notify(hNotifier, type, text);
UINT windowStyle = GetWindowStyle(hNotifier);
if (0 == (WS_VISIBLE & windowStyle))
{
ShowWindow(hNotifier, SW_SHOWNA);
}
if (FALSE != playBeep)
LoginNotifier_PlayBeep(hNotifier);
}
void LoginPopup::SetAlert(UINT type, LPCWSTR message)
{
alertType = type;
if (FALSE == IS_INTRESOURCE(alertMessage))
LoginBox_FreeString(alertMessage);
if (NULL == message)
{
alertMessage = NULL;
return;
}
if (IS_INTRESOURCE(message))
alertMessage = (LPWSTR)message;
else
alertMessage = LoginBox_CopyString(message);
}
void LoginPopup::RemoveAlert()
{
SetAlert(-1, NULL);
}
LRESULT LoginPopup::SendNotification(UINT code, NMHDR *pnmh)
{
if (NULL == pnmh) return 0L;
HWND hParent = GetAncestor(hwnd, GA_PARENT);
if(NULL == hParent) return 0L;
pnmh->code = code;
pnmh->hwndFrom = hwnd;
pnmh->idFrom = (UINT_PTR)GetWindowLongPtr(hwnd, GWLP_ID);
return SendMessage(hParent, WM_NOTIFY, (WPARAM)pnmh->idFrom, (LPARAM)pnmh);
}
BOOL LoginPopup::GetInfoRect(RECT *rect)
{
if (NULL == rect)
return FALSE;
LONG notifierHeight = 0;
HWND hNotifier = GetDlgItem(hwnd, IDC_NOTIFIER);
if (NULL != hNotifier && 0 != (WS_VISIBLE & GetWindowStyle(hNotifier)) &&
FALSE != GetWindowRect(hNotifier, rect))
{
notifierHeight = rect->bottom - rect->top;
if (notifierHeight < 0) notifierHeight = 0;
}
if (FALSE == GetClientRect(hwnd, rect))
return FALSE;
rect->left += (clientMargins.left + infoMargins.left);
rect->right -= (clientMargins.right + infoMargins.right);
if (0 != notifierHeight)
rect->top += (notifierHeight + infoMargins.top);
else
rect->top += (clientMargins.top + infoMargins.top);
if (buttonHeight > 0)
rect->bottom -= (2 * clientMargins.bottom + buttonHeight + infoMargins.bottom);
else
rect->bottom -= (clientMargins.bottom + infoMargins.bottom);
if (rect->right < rect->left) rect->right = rect->left;
if (rect->bottom < rect->top) rect->bottom = rect->top;
return TRUE;
}
BOOL LoginPopup::CalculateWindowRect(LONG infoWidth, LONG infoHeight, const INT *buttonList, UINT buttonCount, BOOL includeTitle, RECT *rect)
{
if (NULL == rect)
return FALSE;
if (infoWidth < 110) infoWidth = 110;
if (infoHeight < 32) infoHeight = 32;
LONG minWidth = 0;
LONG notifierHeight = 0;
HWND hNotifier = GetDlgItem(hwnd, IDC_NOTIFIER);
if (NULL != hNotifier && 0 != (WS_VISIBLE & GetWindowStyle(hNotifier)) &&
FALSE != GetWindowRect(hNotifier, rect))
{
notifierHeight = rect->bottom - rect->top;
if (notifierHeight < 0) notifierHeight = 0;
if (FALSE != includeTitle)
{
SIZE size;
if (FALSE != LoginNotifier_GetIdealSize(hNotifier, &size))
minWidth = size.cx + clientMargins.right;
}
}
if (NULL != buttonList && buttonCount > 0 &&
((HDWP)TRUE) == LayoutButtons(NULL, buttonList, buttonCount, FALSE, rect))
{
LONG buttonWidth = (rect->right - rect->left) + clientMargins.left + clientMargins.right;
if (buttonWidth > minWidth)
minWidth = buttonWidth;
}
rect->left = 0;
rect->top = 0;
rect->right = rect->left + infoWidth;
rect->bottom = rect->top + infoHeight;
rect->right += (clientMargins.left + infoMargins.left + clientMargins.right + infoMargins.right);
if ((rect->right - rect->left) < minWidth)
rect->right = rect->left + minWidth;
rect->bottom += (0 != notifierHeight) ?
(notifierHeight + infoMargins.top) : (clientMargins.top + infoMargins.top);
rect->bottom += (buttonHeight > 0) ?
(2 * clientMargins.bottom + buttonHeight + infoMargins.bottom) : (clientMargins.bottom + infoMargins.bottom);
return TRUE;
}
HDWP LoginPopup::LayoutButtons(HDWP hdwp, const INT *buttonList, UINT buttonCount, BOOL redraw, RECT *rectOut)
{
RECT rect;
GetClientRect(hwnd, &rect);
rect.left += clientMargins.left;
rect.top += clientMargins.top;
rect.right -= clientMargins.right;
rect.bottom -= clientMargins.bottom;
return LoginBox_LayoutButtonBar(hdwp, hwnd, buttonList, buttonCount, &rect,
buttonHeight, buttonSpace, redraw, rectOut);
}
BOOL LoginPopup::GetTextSize(HWND hText, LONG width, SIZE *size)
{
if (NULL == hText) return FALSE;
WCHAR szBuffer[4096] = {0};
INT cchLen = (INT)SendMessage(hText, WM_GETTEXT, ARRAYSIZE(szBuffer), (LPARAM)szBuffer);
if (0 == cchLen)
{
size->cx = 0;
size->cy = 0;
return TRUE;
}
HDC hdc = GetDCEx(hText, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
if (NULL == hdc)
return FALSE;
HFONT font = (HFONT)SendMessage(hText, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, font);
BOOL resultOk;
RECT rect;
SetRect(&rect, 0, 0, width, 0);
resultOk = DrawText(hdc, szBuffer, cchLen, &rect,
DT_CALCRECT | DT_EXTERNALLEADING | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK);
if(FALSE != resultOk)
{
size->cx = (rect.right - rect.left);
size->cy = (rect.bottom - rect.top);
}
SelectObject(hdc, fontOrig);
ReleaseDC(hText, hdc);
return resultOk;
}
BOOL LoginPopup::OnInitDialog(HWND hFocus, LPARAM param)
{
RegisterPopup(hwnd, TRUE);
RECT rect;
if (FALSE == GetWindowRect(hwnd, &rect))
SetRectEmpty(&rect);
idealSize.cx = rect.right - rect.left;
idealSize.cy = rect.bottom - rect.top;
HWND hNotifier = LoginNotifier_CreateWindow(0, WS_CHILD | WS_CLIPSIBLINGS, 0, 0, 0, 0, hwnd, IDC_NOTIFIER);
if (NULL != hNotifier)
{
HFONT hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
if (NULL != hFont)
SendMessage(hNotifier, WM_SETFONT, (WPARAM)hFont, 0L);
#ifdef COLOR_TITLE
LoginNotifier_SetBkColor(hNotifier, GetSysColor(COLOR_TITLE));
#endif //COLOR_TITLE
#ifdef COLOR_TITLETEXT
LoginNotifier_SetTextColor(hNotifier, GetSysColor(COLOR_TITLETEXT));
#endif //COLOR_TITLETEXT
UpdateTitle(FALSE);
}
UpdateMargins();
UpdateLayout(FALSE);
PostMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0L);
return FALSE;
}
void LoginPopup::OnDestroy()
{
}
void LoginPopup::OnWindowPosChanged(const WINDOWPOS *pwp)
{
if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
UpdateLayout(0 == (SWP_NOREDRAW & pwp->flags));
}
void LoginPopup::OnCommand(UINT commandId, UINT eventType, HWND hControl)
{
switch(commandId)
{
case IDOK:
case IDCANCEL:
EndDialog(commandId);
break;
}
}
LRESULT LoginPopup::OnNotify(UINT controlId, const NMHDR *pnmh)
{
return FALSE;
}
void LoginPopup::OnPaint()
{
PAINTSTRUCT ps;
if (BeginPaint(hwnd, &ps))
{
if (ps.rcPaint.left != ps.rcPaint.right)
Paint(ps.hdc, &ps.rcPaint, ps.fErase);
EndPaint(hwnd, &ps);
}
}
void LoginPopup::OnPrintClient(HDC hdc, UINT options)
{
if (0 != (PRF_CLIENT & options))
{
RECT clientRect;
if (GetClientRect(hwnd, &clientRect))
Paint(hdc, &clientRect, TRUE);
}
}
HBRUSH LoginPopup::OnGetStaticColor(HDC hdc, HWND hControl)
{
HBRUSH hb = (HBRUSH)GetSysColorBrush(COLOR_CLIENT);
SetTextColor(hdc, GetSysColor(COLOR_CLIENTTEXT));
SetBkColor(hdc, GetSysColor(COLOR_CLIENT));
return hb;
}
void LoginPopup::OnSetFont(HFONT font, BOOL redraw)
{
DefDlgProc(hwnd, WM_SETFONT, (WPARAM)font, MAKELPARAM(redraw, 0));
UpdateMargins();
}
void LoginPopup::OnParentNotify(UINT eventId, UINT wParam, LPARAM lParam)
{
}
BOOL LoginPopup::OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut)
{
if (NULL == clientRect || NULL == rectOut)
return FALSE;
LONG width = idealSize.cx;
LONG height = idealSize.cy;
rectOut->left = clientRect->left + ((clientRect->right - clientRect->left) - width)/2;
rectOut->top = clientRect->top+ ((clientRect->bottom - clientRect->top) - height)/2;
rectOut->right = rectOut->left + width;
rectOut->bottom = rectOut->top + height;
return TRUE;
}
void LoginPopup::OnPlayBeep()
{
LoginBox_MessageBeep(MB_ICONASTERISK);
}
INT_PTR LoginPopup::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
case WM_DESTROY: OnDestroy(); return TRUE;
case WM_NOTIFY: MSGRESULT(hwnd, OnNotify((INT)wParam, (NMHDR*)lParam));
case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
case WM_WINDOWPOSCHANGED: OnWindowPosChanged((WINDOWPOS*)lParam); return TRUE;
case WM_SIZE: return TRUE;
case WM_SETFONT: OnSetFont((HFONT)wParam, (BOOL)LOWORD(lParam)); return TRUE;
case WM_ERASEBKGND: MSGRESULT(hwnd, 0);
case WM_PAINT: OnPaint(); return TRUE;
case WM_PRINTCLIENT: OnPrintClient((HDC)wParam, (UINT)lParam); return TRUE;
case WM_CTLCOLORSTATIC: return (INT_PTR)OnGetStaticColor((HDC)wParam, (HWND)lParam);
case WM_PARENTNOTIFY: OnParentNotify(LOWORD(wParam), HIWORD(wParam), lParam); return TRUE;
case NLPOPUP_UPDATEWNDPOS: MSGRESULT(hwnd, OnUpdateWindowPos((const RECT*)wParam, (RECT*)lParam));
case NLPOPUP_PLAYBEEP: OnPlayBeep(); return TRUE;
}
return FALSE;
}
static INT_PTR CALLBACK LoginPopup_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static ATOM LOGINPOPUP_PROP = 0;
LoginPopup *popup = (LoginPopup*)GetProp(hwnd, MAKEINTATOM(LOGINPOPUP_PROP));
if (NULL == popup)
{
switch(uMsg)
{
case WM_INITDIALOG:
if (0 == LOGINPOPUP_PROP)
{
LOGINPOPUP_PROP = GlobalAddAtomW(L"NullsoftLoginPopupProp");
if (0 == LOGINPOPUP_PROP)
return 0;
}
if (NULL != lParam)
{
LOGINPOPUPCREATEPARAM *create = (LOGINPOPUPCREATEPARAM*)lParam;
lParam = create->lParam;
if (SUCCEEDED(create->fnCreator(hwnd, lParam, &popup)))
{
if (FALSE == SetProp(hwnd, MAKEINTATOM(LOGINPOPUP_PROP), (HANDLE)popup))
{
delete(popup);
popup = NULL;
}
}
}
if (NULL != popup)
return popup->DialogProc(uMsg, wParam, lParam);
break;
}
return 0;
}
INT_PTR result = popup->DialogProc(uMsg, wParam, lParam);
if (WM_NCDESTROY == uMsg)
{
RemoveProp(hwnd, MAKEINTATOM(LOGINPOPUP_PROP));
delete(popup);
}
return result;
}
static LRESULT CALLBACK LoginPopup_MessageFilter(INT code, WPARAM wParam, LPARAM lParam)
{
THREADPOPUPDATA *data = (NULL != WASABI_API_APP && TLS_OUT_OF_INDEXES != threadStorage) ?
(THREADPOPUPDATA*)WASABI_API_APP->GetThreadStorage(threadStorage) : NULL;
if (NULL == data)
return 0;
if (code >= 0)
{
MSG *pMsg = (MSG*)lParam;
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
if (L'C' == pMsg->wParam && 0 == (0x40000000 & pMsg->lParam) &&
0 != (0x8000 & GetAsyncKeyState(VK_MENU)))
{
pMsg->wParam = VK_ESCAPE;
}
if ((VK_ESCAPE == pMsg->wParam || VK_RETURN == pMsg->wParam) &&
0 == (0x40000000 & pMsg->lParam))
{
size_t index = data->windowList.size();
while(index--)
{
HWND hPopup = data->windowList[index];
if (IsChild(hPopup, pMsg->hwnd))
{
INT commandId;
switch(pMsg->wParam)
{
case VK_ESCAPE:
commandId = IDCANCEL;
break;
case VK_RETURN:
if (0 != (DLGC_BUTTON & SendMessage(pMsg->hwnd, WM_GETDLGCODE, 0, 0L)) &&
IsWindowVisible(pMsg->hwnd) && IsWindowEnabled(pMsg->hwnd))
{
commandId = (INT)(INT_PTR)GetWindowLongPtr(pMsg->hwnd, GWLP_ID);
}
else
{
commandId = (INT)(INT_PTR)SendMessage(hPopup, DM_GETDEFID, 0, 0L);
if (DC_HASDEFID != HIWORD(commandId))
commandId = IDOK;
}
break;
}
SendMessage(hPopup, WM_COMMAND, MAKEWPARAM(commandId, 0), (LPARAM)pMsg->hwnd);
return 1;
}
}
}
// add mnemonic support here (http://msdn.microsoft.com/en-us/library/ms644995%28VS.85%29.aspx)
//HWND hPopup;
//size_t index = data->windowList.size();
//while(index--)
//{
// hPopup = data->windowList[index];
// if (pMsg->hwnd == hPopup || IsChild(hPopup, pMsg->hwnd))
// {
//
// }
//}
}
}
return CallNextHookEx(data->hHook, code, wParam, lParam);
}

View File

@@ -0,0 +1,100 @@
#ifndef NULLSOFT_AUTH_LOGINPOPUP_HEADER
#define NULLSOFT_AUTH_LOGINPOPUP_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
// messages
#define NLPOPUP_FIRST (WM_APP + 100)
#define NLPOPUP_UPDATEWNDPOS (NLPOPUP_FIRST + 0) // wParam - (WPARAM)(const RECT*)clientRect, lParam = (LPARAM)(RECT*)popupRectOut; Return TRUE if you set controlRect;
#define LoginPopup_UpdateWindowPos(/*HWND*/ __hwnd, /*const RECT* */__clientRect, /*RECT* */__popupRectOut)\
((BOOL)SNDMSG((__hwnd), NLPOPUP_UPDATEWNDPOS, (WPARAM)(__clientRect), (LPARAM)(__popupRectOut)))
#define NLPOPUP_PLAYBEEP (NLPOPUP_FIRST + 1) // wParam - not used, lParam - not used; Return ignored
#define LoginPopup_PlayBeep(/*HWND*/ __hwnd)\
(SNDMSG((__hwnd), NLPOPUP_PLAYBEEP, 0, 0L))
// notifications
#define NLPOPUPN_FIRST (100)
typedef struct __NLPNRESULT
{
NMHDR hdr;
INT_PTR exitCode;
} NLPNRESULT;
#define NLPN_RESULT (NLPOPUPN_FIRST + 0)
class __declspec(novtable) LoginPopup
{
public:
typedef HRESULT (CALLBACK *Creator)(HWND /*hwnd*/, LPARAM /*param*/, LoginPopup** /*instance*/);
typedef BOOL (CALLBACK *Enumerator)(HWND /*hwnd*/, LPARAM /*param*/);
protected:
LoginPopup(HWND hwnd, UINT popupType, LPCWSTR pszTitle);
virtual ~LoginPopup();
protected:
static HWND CreatePopup(LPCWSTR pszTemplate, HWND hParent, LPARAM param, Creator fnCreator);
public:
static BOOL RegisterPopup(HWND hwnd, BOOL fRegister);
static BOOL EnumeratePopups(HWND hHost, Enumerator callback, LPARAM param);
static BOOL AnyPopup(HWND hHost);
protected:
virtual void UpdateLayout(BOOL fRedraw);
virtual void Paint(HDC hdc, const RECT *prcPaint, BOOL fErase);
virtual void EndDialog(INT_PTR code);
virtual void UpdateMargins();
virtual void SetTitle(UINT type, LPCWSTR title);
virtual void SetAlert(UINT type, LPCWSTR message);
virtual void RemoveAlert();
virtual void UpdateTitle(BOOL playBeep);
BOOL GetInfoRect(RECT *rect);
BOOL CalculateWindowRect(LONG infoWidth, LONG infoHeight, const INT *buttonList, UINT buttonCount, BOOL includeTitle, RECT *rect);
HDWP LayoutButtons(HDWP hdwp, const INT *buttonList, UINT buttonCount, BOOL redraw, RECT *rectOut);
LRESULT SendNotification(UINT code, NMHDR *pnmh);
BOOL GetTextSize(HWND hText, LONG width, SIZE *size);
protected:
virtual BOOL OnInitDialog(HWND hFocus, LPARAM param);
virtual void OnDestroy();
virtual void OnCommand(UINT commandId, UINT eventType, HWND hControl);
virtual LRESULT OnNotify(UINT controlId, const NMHDR *pnmh);
virtual HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
virtual void OnParentNotify(UINT eventId, UINT wParam, LPARAM lParam);
void OnPaint();
void OnWindowPosChanged(const WINDOWPOS *pwp);
void OnPrintClient(HDC hdc, UINT options);
void OnSetFont(HFONT font, BOOL redraw);
virtual BOOL OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut);
virtual void OnPlayBeep();
virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
friend static INT_PTR CALLBACK LoginPopup_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
friend static LRESULT CALLBACK LoginPopup_MessageFilter(INT code, WPARAM wParam, LPARAM lParam);
protected:
HWND hwnd;
SIZE idealSize;
RECT clientMargins;
RECT infoMargins;
LONG buttonHeight;
LONG buttonSpace;
UINT popupType;
UINT alertType;
LPWSTR alertMessage;
};
#endif //NULLSOFT_AUTH_LOGINPOPUP_HEADER

View File

@@ -0,0 +1,231 @@
#include "./loginProvider.h"
#include "./loginTemplate.h"
#include "./loginCommand.h"
#include "./common.h"
#include <strsafe.h>
static HRESULT LoginProvider_SetString(LPWSTR *ppszTarget, LPCWSTR pszSource)
{
if (NULL == ppszTarget)
return E_POINTER;
if (NULL != *ppszTarget)
free(*ppszTarget);
if (NULL == pszSource)
*ppszTarget = NULL;
else
{
*ppszTarget = LoginBox_CopyString(pszSource);
if (NULL == *ppszTarget) return E_OUTOFMEMORY;
}
return S_OK;
}
LoginProvider::LoginProvider(const GUID *providerUid)
: ref(1), name(NULL), description(NULL), imagePath(NULL), tosUrl(NULL),
privacyUrl(NULL), helpUrl(NULL), pageTemplate(NULL), command(NULL)
{
id = (NULL != providerUid) ? *providerUid : GUID_NULL;
}
LoginProvider::~LoginProvider()
{
LoginBox_FreeString(name);
LoginBox_FreeString(description);
LoginBox_FreeString(imagePath);
LoginBox_FreeString(tosUrl);
LoginBox_FreeString(privacyUrl);
LoginBox_FreeString(helpUrl);
if (NULL != pageTemplate) pageTemplate->Release();
if (NULL != command) command->Release();
}
HRESULT LoginProvider::CreateInstance(const GUID *providerUid, LoginProvider **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == providerUid) return E_INVALIDARG;
*instance = new LoginProvider(providerUid);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
ULONG LoginProvider::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginProvider::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginProvider::IsIdentical(LoginProvider *test)
{
if (NULL == test)
return E_INVALIDARG;
if (FALSE == IsEqualGUID(id, test->id))
return S_FALSE;
if (S_OK != LoginBox_IsStrEq(name, test->name) ||
S_OK != LoginBox_IsStrEq(description, test->description) ||
S_OK != LoginBox_IsStrEqInvI(imagePath, test->imagePath) ||
S_OK != LoginBox_IsStrEqInvI(tosUrl, test->tosUrl) ||
S_OK != LoginBox_IsStrEqInvI(privacyUrl, test->privacyUrl) ||
S_OK != LoginBox_IsStrEqInvI(helpUrl, test->helpUrl))
{
return S_FALSE;
}
if ((NULL == pageTemplate) != (NULL == test->pageTemplate))
return S_FALSE;
if (NULL != pageTemplate)
{
HRESULT hr = pageTemplate->IsIdentical(test->pageTemplate);
if (S_OK != hr) return hr;
}
if ((NULL == command) != (NULL == test->command))
return S_FALSE;
if (NULL != command)
{
HRESULT hr = command->IsIdentical(test->command);
if (S_OK != hr) return hr;
}
return S_OK;
}
HRESULT LoginProvider::IsValid()
{
return (NULL != pageTemplate && NULL != command) ? S_OK :S_FALSE;
}
HRESULT LoginProvider::GetId(GUID *pId)
{
if (NULL == pId) return E_POINTER;
*pId = id;
return S_OK;
}
HRESULT LoginProvider::GetName(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, name, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetDescription(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, description, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetImagePath(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, imagePath, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetTosLink(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, tosUrl, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetPrivacyLink(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, privacyUrl, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetHelpLink(LPWSTR pszBuffer, UINT cchBufferMax)
{
if (NULL == pszBuffer) return E_INVALIDARG;
return StringCchCopyEx(pszBuffer, cchBufferMax, helpUrl, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT LoginProvider::GetTemplate(LoginTemplate **ppTemplate)
{
if (NULL == ppTemplate)
return E_POINTER;
*ppTemplate = pageTemplate;
if (NULL != pageTemplate)
pageTemplate->AddRef();
return S_OK;
}
HRESULT LoginProvider::GetCommand(LoginCommand **ppCommand)
{
if (NULL == ppCommand)
return E_POINTER;
*ppCommand = command;
if (NULL != command)
command->AddRef();
return S_OK;
}
HRESULT LoginProvider::SetName(LPCWSTR pszName)
{
return LoginProvider_SetString(&name, pszName);
}
HRESULT LoginProvider::SetDescription(LPCWSTR pszDescription)
{
return LoginProvider_SetString(&description, pszDescription);
}
HRESULT LoginProvider::SetImagePath(LPCWSTR pszImagePath)
{
return LoginProvider_SetString(&imagePath, pszImagePath);
}
HRESULT LoginProvider::SetTosLink(LPCWSTR pszUrl)
{
return LoginProvider_SetString(&tosUrl, pszUrl);
}
HRESULT LoginProvider::SetPrivacyLink(LPCWSTR pszUrl)
{
return LoginProvider_SetString(&privacyUrl, pszUrl);
}
HRESULT LoginProvider::SetHelpLink(LPCWSTR pszUrl)
{
return LoginProvider_SetString(&helpUrl, pszUrl);
}
HRESULT LoginProvider::SetTemplate(LoginTemplate *pTemplate)
{
if (NULL != pageTemplate) pageTemplate->Release();
pageTemplate = pTemplate;
if (NULL != pageTemplate) pageTemplate->AddRef();
return S_OK;
}
HRESULT LoginProvider::SetCommand(LoginCommand *pCommand)
{
if (NULL != command) command->Release();
command = pCommand;
if (NULL != command) command->AddRef();
return S_OK;
}

View File

@@ -0,0 +1,64 @@
#ifndef NULLSOFT_AUTH_LOGINPROVIDER_HEADER
#define NULLSOFT_AUTH_LOGINPROVIDER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginTemplate;
class LoginCommand;
class LoginProvider
{
protected:
LoginProvider(const GUID *providerUid);
virtual ~LoginProvider();
public:
static HRESULT CreateInstance(const GUID *providerUid, LoginProvider **instance);
public:
ULONG AddRef();
ULONG Release();
HRESULT IsIdentical(LoginProvider *test);
HRESULT IsValid();
// get
HRESULT GetId(GUID *pId);
HRESULT GetName(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetDescription(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetImagePath(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetTosLink(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetPrivacyLink(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetHelpLink(LPWSTR pszBuffer, UINT cchBufferMax);
HRESULT GetTemplate(LoginTemplate **ppTemplate);
HRESULT GetCommand(LoginCommand **ppCommand);
// set
HRESULT SetName(LPCWSTR pszName);
HRESULT SetDescription(LPCWSTR pszDescription);
HRESULT SetImagePath(LPCWSTR pszImagePath);
HRESULT SetTosLink(LPCWSTR pszUrl);
HRESULT SetPrivacyLink(LPCWSTR pszUrl);
HRESULT SetHelpLink(LPCWSTR pszUrl);
HRESULT SetTemplate(LoginTemplate *pTemplate);
HRESULT SetCommand(LoginCommand *pCommand);
protected:
ULONG ref;
GUID id;
LPWSTR name;
LPWSTR description;
LPWSTR imagePath;
LPWSTR tosUrl;
LPWSTR privacyUrl;
LPWSTR helpUrl;
LoginTemplate *pageTemplate;
LoginCommand *command;
};
#endif //NULLSOFT_AUTH_LOGINPROVIDER_HEADER

View File

@@ -0,0 +1,35 @@
#ifndef NULLSOFT_AUTH_LOGINRESULT_HEADER
#define NULLSOFT_AUTH_LOGINRESULT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginData;
class __declspec(novtable) LoginResult : public IUnknown
{
public:
typedef void (CALLBACK *Callback)(LoginResult *result);
protected:
LoginResult() {}
~LoginResult() {}
public:
virtual HRESULT GetLoginData(LoginData **loginData) = 0;
virtual HRESULT GetWaitHandle(HANDLE *handle) = 0;
virtual HRESULT GetUser(void **user) = 0;
virtual HRESULT RequestAbort(BOOL fDrop) = 0;
virtual HRESULT IsCompleted() = 0;
virtual HRESULT IsAborting() = 0;
};
#endif //NULLSOFT_AUTH_LOGINRESULT_HEADER

View File

@@ -0,0 +1,159 @@
#include "./loginStatus.h"
#include "./common.h"
LoginStatus::LoginStatus(HWND hTarget)
: ref(1), hwnd(hTarget)
{
InitializeCriticalSection(&lock);
}
LoginStatus::~LoginStatus()
{
DeleteCriticalSection(&lock);
}
HRESULT LoginStatus::CreateInstance(HWND hTarget, LoginStatus **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new LoginStatus(hTarget);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
ULONG LoginStatus::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginStatus::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
UINT LoginStatus::Add(BSTR status)
{
EnterCriticalSection(&lock);
Record r;
r.cookie = GetNextCookie();
r.text = status;
list.push_back(r);
LeaveCriticalSection(&lock);
UpdateWindowText();
return r.cookie;
}
BOOL LoginStatus::Set(UINT cookie, BSTR status)
{
BOOL foundOk = FALSE;
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (cookie == list[index].cookie)
{
SysFreeString(list[index].text);
list[index].text = status;
foundOk = TRUE;
break;
}
}
LeaveCriticalSection(&lock);
UpdateWindowText();
return foundOk;
}
void LoginStatus::Remove(UINT cookie)
{
EnterCriticalSection(&lock);
size_t index = list.size();
while(index--)
{
if (cookie == list[index].cookie)
{
SysFreeString(list[index].text);
list.eraseAt(index);
break;
}
}
LeaveCriticalSection(&lock);
UpdateWindowText();
}
BOOL LoginStatus::AttachWindow(HWND hTarget)
{
DetachWindow();
hwnd = hTarget;
UpdateWindowText();
return TRUE;
}
BOOL LoginStatus::DetachWindow()
{
hwnd = NULL;
return TRUE;
}
UINT LoginStatus::GetNextCookie()
{
size_t i, count;
count = list.size();
UINT cookie = (UINT)count;
do
{
for (i = 0; i < count; i++)
{
if (list[i].cookie == cookie)
{
cookie++;
break;
}
}
} while(i != count);
return cookie;
}
BOOL LoginStatus::UpdateWindowText()
{
EnterCriticalSection(&lock);
BOOL resultOk = FALSE;
if (NULL != hwnd)
{
BSTR text = NULL;
size_t index = list.size();
while(index--)
{
if (NULL != list[index].text && L'\0' != list[index].text)
{
text = list[index].text;
break;
}
}
resultOk = (BOOL)SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)text);
}
LeaveCriticalSection(&lock);
return resultOk;
}

View File

@@ -0,0 +1,53 @@
#ifndef NULLSOFT_AUTH_LOGIN_STATUS_HEADER
#define NULLSOFT_AUTH_LOGIN_STATUS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../nu/Vectors.h"
class LoginStatus
{
protected:
LoginStatus(HWND hTarget);
~LoginStatus();
public:
static HRESULT CreateInstance(HWND hTarget, LoginStatus **instance);
public:
ULONG AddRef();
ULONG Release();
UINT Add(BSTR status);
BOOL Set(UINT cookie, BSTR status);
void Remove(UINT cookie);
BOOL AttachWindow(HWND hTarget);
BOOL DetachWindow();
protected:
BOOL UpdateWindowText();
UINT GetNextCookie();
protected:
typedef struct __Record
{
UINT cookie;
BSTR text;
} Record;
typedef Vector<Record> RecordList;
protected:
ULONG ref;
HWND hwnd;
RecordList list;
CRITICAL_SECTION lock;
};
#endif //NULLSOFT_AUTH_LOGIN_STATUS_HEADER

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
#ifndef NULLSOFT_AUTH_LOGIN_TAB_HEADER
#define NULLSOFT_AUTH_LOGIN_TAB_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <commctrl.h>
#define NWC_LOGINTAB L"NullsoftLoginTab"
BOOL LoginTab_RegisterClass(HINSTANCE hInstance);
HWND LoginTab_CreateWindow(UINT styleEx, LPCWSTR pszTitle, UINT style, INT x, INT y, INT cx, INT cy, HWND hParent, INT_PTR controlId);
typedef struct __NLTITEM
{
UINT mask;
UINT dwState;
UINT dwStateMask;
LPWSTR pszText;
UINT cchTextMax;
UINT iImage;
UINT iImageActive;
UINT iImageDisabled;
LPARAM param;
} NLTITEM;
// Item mask flags
#define NLTIF_STATE 0x00000001
#define NLTIF_TEXT 0x00000002
#define NLTIF_PARAM 0x00000004
#define NLTIF_IMAGE_MASK (NLTIF_IMAGE | NLTIF_IMAGE_ACTIVE | NLTIF_IMAGE_DISABLED)
#define NLTIF_IMAGE 0x00000010
#define NLTIF_IMAGE_ACTIVE 0x00000020
#define NLTIF_IMAGE_DISABLED 0x00000040
// Item states
#define NLTIS_PRESSED 0x00000001
#define NLTIS_HIGHLIGHTED 0x00000002
#define NLTIS_SELECTED 0x00000004
#define NLTIS_DISABLED 0x00000008
// image index values
#define NLTM_IMAGE_NONE ((UINT)-1)
#define NLTM_IMAGE_CALLBACK ((UINT)-2)
// Messages
#define NLTM_FIRST (WM_USER + 10)
#define NLTM_GETIDEALHEIGHT (NLTM_FIRST + 0) // wParam - not used, lParam - not used; Return ideal height.
#define LoginTab_GetIdealHeight(/*HWND*/ __hwnd)\
((INT)SNDMSG((__hwnd), NLTM_GETIDEALHEIGHT, 0, 0L))
#define NLTM_INSERTITEM (NLTM_FIRST + 1) // wParam = (WPARAM)(INT)iItem, lParam = (LPARAM)(NLTITEM*)pItem; Return = index of new item or -1.
#define LoginTab_InsertItem(/*HWND*/ __hwnd, /*INT*/ __iItem, /*NLTITEM* */ __pItem)\
((INT)SNDMSG((__hwnd), NLTM_INSERTITEM, (WPARAM)(__iItem), (LPARAM)(__pItem)))
#define NLTM_SETITEM (NLTM_FIRST + 2) // wParam = (WPARAM)(INT)iItem, lParam = (LPARAM)(NLTITEM*)pItem; Return = TRUE on success.
#define LoginTab_SetItem(/*HWND*/ __hwnd, /*INT*/ __iItem, /*NLTITEM* */ __pItem)\
((BOOL)SNDMSG((__hwnd), NLTM_SETITEM, (WPARAM)(__iItem), (LPARAM)(__pItem)))
#define NLTM_GETITEM (NLTM_FIRST + 3) // wParam = (WPARAM)(INT)iItem, lParam = (LPARAM)(NLTITEM*)pItem; Return = TRUE on success.
#define LoginTab_GetItem(/*HWND*/ __hwnd, /*INT*/ __iItem, /*NLTITEM* */ __pItem)\
((BOOL)SNDMSG((__hwnd), NLTM_GETITEM, (WPARAM)(__iItem), (LPARAM)(__pItem)))
#define NLTM_DELETEITEM (NLTM_FIRST + 4) // wParam = (WPARAM)(INT)iItem, lParam - not used; Return = TRUE on success.
#define LoginTab_DeleteItem(/*HWND*/ __hwnd, /*INT*/ __iItem)\
((BOOL)SNDMSG((__hwnd), NLTM_DELETEITEM, (WPARAM)(__iItem), 0L))
#define NLTM_DELETEALLITEMS (NLTM_FIRST + 5) // wParam - not used, lParam - not used; Return = TRUE on success.
#define LoginTab_DeleteAllItems(/*HWND*/ __hwnd)\
((BOOL)SNDMSG((__hwnd), NLTM_DELETEALLITEMS, 0, 0L))
#define NLTM_GETITEMCOUNT (NLTM_FIRST + 6) // wParam - not used, lParam - not used; Return item count.
#define LoginTab_GetItemCount(/*HWND*/ __hwnd)\
((INT)SNDMSG((__hwnd), NLTM_GETITEMCOUNT, 0, 0L))
#define NLTM_GETCURSEL (NLTM_FIRST + 7) // wParam - not used, lParam - not used; Return item index or -1
#define LoginTab_GetCurSel(/*HWND*/ __hwnd)\
((INT)SNDMSG((__hwnd), NLTM_GETCURSEL, 0, 0L))
#define NLTM_SETCURSEL (NLTM_FIRST + 8) // wParam = (WPARAM)(INT)iItem, lParam - not used; Return index of previously selected item if successful, or -1.
#define LoginTab_SetCurSel(/*HWND*/ __hwnd, /*INT*/ __iItem)\
((INT)SNDMSG((__hwnd), NLTM_SETCURSEL, (WPARAM)(__iItem), 0L))
#define NLTM_SETIMAGELIST (NLTM_FIRST + 9) // wParam - not used, lParam - (LPARAM)(HIMAGELIST)himl; Returns the handle to the previous image list, or NULL if there is no previous image list.
#define LoginTab_SetImageList(/*HWND*/ __hwnd, /*HIMAGELIST*/ __himl)\
((HIMAGELIST)SNDMSG((__hwnd), NLTM_SETIMAGELIST, 0, (LPARAM)(__himl)))
#define NLTM_GETIMAGELIST (NLTM_FIRST + 10) // wParam - not used, lParam - not used; Returns the handle to the image list if successful, or NULL otherwise.
#define LoginTab_GetImageList(/*HWND*/ __hwnd)\
((HIMAGELIST)SNDMSG((__hwnd), NLTM_GETIMAGELIST, 0, 0L))
#define NLTM_RESETORDER (NLTM_FIRST + 11) // wParam - not used, lParam - not used; Return - ignored
#define LoginTab_ResetOrder(/*HWND*/ __hwnd)\
(SNDMSG((__hwnd), NLTM_RESETORDER, 0, 0L))
#define NLTM_LOCKSELECTION (NLTM_FIRST + 12) // wParam - (BOOL)fLock, lParam - not used; Return - ignored.
#define LoginTab_LockSelection(/*HWND*/ __hwnd, /*BOOL*/ __fLock)\
(SNDMSG((__hwnd), NLTM_LOCKSELECTION, (WPARAM)(__fLock), 0L))
#define NLTM_GETIDEALWIDTH (NLTM_FIRST + 13) // wParam = (WPARAM)(INT)itemCount, lParam - not used; Return ideal width.
#define LoginTab_GetIdealWidth(/*HWND*/ __hwnd, /*INT*/ __itemCount)\
((INT)SNDMSG((__hwnd), NLTM_GETIDEALWIDTH, (WPARAM)(__itemCount), 0L))
// Notifications
typedef struct __NMLOGINTAB
{
NMHDR hdr;
INT iItem;
} NMLOGINTAB;
typedef struct __NMLOGINTABHELP
{
NMHDR hdr;
INT iItem;
LPARAM param;
BSTR bstrHelp;
} NMLOGINTABHELP;
typedef struct __NMLOGINTABCLICK
{
NMHDR hdr;
POINT pt;
} NMLOGINTABCLICK;
typedef struct __NMLOGINTABIMAGE
{
NMHDR hdr;
INT iItem;
LPARAM param;
HIMAGELIST imageList;
UINT maskRequest;
UINT maskUpdate;
UINT iImage;
UINT iImageActive;
UINT iImageDisabled;
} NMLOGINTABIMAGE;
#define NLTN_FIRST (0 + 10)
#define NLTN_SELCHANGE (NLTN_FIRST + 0) // pnmh = (NMHDR*)lParam;
#define NLTN_DELETEITEM (NLTN_FIRST + 1) // pnmh = (NMLOGINTAB*)lParam;
#define NLTN_DELETEALLITEMS (NLTN_FIRST + 2) // pnmh = (NMLOGINTAB*)lParam; iItem = -1, return TRUE if you don't want to receive NLTN_DELETEITEM
#define NLTN_GETITEMHELP (NLTN_FIRST + 3) // pnmh = (NMLOGINTABHELP*)lParam;
#define NLTN_GETITEMIMAGE (NLTN_FIRST + 4) // pnmh = (NMLOGINTABIMAGE*)lParam;
// common notifications
//NM_RCLICK - pnmh = (NMLOGINTABCLICK*)lParam;
//styles
#define NLTS_LOCKED 0x00000001
#endif //NULLSOFT_AUTH_LOGIN_TAB_HEADER

View File

@@ -0,0 +1,30 @@
#ifndef NULLSOFT_AUTH_LOGIN_TEMPLATE_HEADER
#define NULLSOFT_AUTH_LOGIN_TEMPLATE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class __declspec(novtable) LoginTemplate
{
protected:
LoginTemplate() {}
~LoginTemplate(){}
public:
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
virtual HRESULT GetType(GUID *templateUid) = 0;
virtual HRESULT SetParameter(LPCWSTR pszKey, LPCWSTR pszValue) = 0;
virtual HRESULT IsValid() = 0;
virtual HRESULT IsIdentical(LoginTemplate *test) = 0;
virtual HWND CreatePage(HWND hLoginbox, HWND hParent) = 0;
};
#endif //NULLSOFT_AUTH_LOGIN_TEMPLATE_HEADER

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_HEADER
#define NULLSOFT_AUTH_LOGINBOX_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class api_auth;
class LoginDownloadResult;
class LoginProviderEnumerator;
class ifc_omcacherecord;
class LoginImageCache;
#define LBS_NOCENTEROWNER 0x00000001
HWND LoginBox_CreateWindow(api_auth *auth, const GUID *pRealm, HWND hOwner, UINT fStyle);
INT_PTR LoginBox_Show(api_auth *auth, const GUID *pRealm, HWND hOwner, UINT fStyle);
HWND LoginBox_FindActive(const GUID *pRealm);
// messages
#define NLBM_FIRST (WM_APP + 10)
#define NLBM_GETAUTHAPI (NLBM_FIRST + 1) // wParam - not used, lParam = (LPARAM)(api_auth**)__authApi; Returns TRUE on success
#define LoginBox_GetAuthApi(/*HNWD*/ __hwnd, /*api_auth** */ __authApi)\
((BOOL)SendMessage((__hwnd), NLBM_GETAUTHAPI, 0, (LPARAM)(__authApi)))
#define NLBM_GETREALM (NLBM_FIRST + 2) // wParam - not used, lParam = (LPARAM)(GUID*)__pGuidRealm; Returns TRUE on success
#define LoginBox_GetRealm(/*HNWD*/ __hwnd, /*GUID* */ __pGuidRealm)\
((BOOL)SendMessage((__hwnd), NLBM_GETREALM, 0, (LPARAM)(__pGuidRealm)))
#define NLBM_GETACTIVEPROVIDER (NLBM_FIRST + 3) // wParam - not used, lParam = (LPARAM)(LoginProvider**)__ppProvider; Returns TRUE on success
#define LoginBox_GetActiveProvider(/*HNWD*/ __hwnd, /*LoginProvider** */ __ppProvider)\
((BOOL)SendMessage((__hwnd), NLBM_GETACTIVEPROVIDER, 0, (LPARAM)(__ppProvider)))
#define NLBM_GETSTATUS (NLBM_FIRST + 4) // wParam - not used, lParam = (LPARAM)(LoginStatus**)ppStatus; Returns TRUE on success
#define LoginBox_GetStatus(/*HNWD*/ __hwnd, /*LoginStatus** */ __ppLoginStatus)\
((BOOL)SendMessage((__hwnd), NLBM_GETSTATUS, 0, (LPARAM)(__ppLoginStatus)))
#define NLBM_ADDSTATUS (NLBM_FIRST + 5) // wParam - not used, lParam = (LPARAM)(BSTR)bstrStatusText; Return - (UINT)statusCookie or -1
#define LoginBox_AddStatus(/*HNWD*/ __hwnd, /*BSTR*/ __bstrStatusText)\
((UINT)SendMessage((__hwnd), NLBM_ADDSTATUS, 0, (LPARAM)(__bstrStatusText)))
#define NLBM_SETSTATUS (NLBM_FIRST + 6) // wParam = (WPARAM)(UINT)statusCookie, lParam = (LPARAM)(BSTR)bstrStatusText; Return TRUE on success.
#define LoginBox_SetStatus(/*HNWD*/ __hwnd, /*UINT*/__statusCookie, /*BSTR*/ __bstrStatusText)\
((BOOL)SendMessage((__hwnd), NLBM_SETSTATUS, (WPARAM)(__statusCookie), (LPARAM)(__bstrStatusText)))
#define NLBM_REMOVESTATUS (NLBM_FIRST + 7) // wParam = (WPARAM)(UINT)statusCookie, lParam - not used. Return ingored.
#define LoginBox_RemoveStatus(/*HNWD*/ __hwnd, /*UINT*/__statusCookie)\
(SendMessage((__hwnd), NLBM_REMOVESTATUS, (WPARAM)(__statusCookie), 0L))
#define NLBM_UPDATEPROVIDERS (NLBM_FIRST + 8) // wParam - (WPARAM)(BOOL)fForce, lParam - not used.
#define LoginBox_UpdateProviders(/*HNWD*/ __hwnd, /*BOOL*/ __forceUpdate)\
((BOOL)SendMessage((__hwnd), NLBM_UPDATEPROVIDERS, (WPARAM)(__forceUpdate), 0L))
#define NLBM_GETUPDATESTATE (NLBM_FIRST + 9) // wParam - not used, lParam - not used. Return TRUE if update active.
#define LoginBox_GetUpdateState(/*HNWD*/ __hwnd)\
((BOOL)SendMessage((__hwnd), NLBM_GETUPDATESTATE, 0, 0L))
#define NLBM_LOGINCOMPLETED (NLBM_FIRST + 20) // wParam - not used, lParam = (LPARAM)(LoginResult*)__pResult;
typedef struct __PROVIDERUPDATERESULT
{
LoginDownloadResult *downloader;
HRESULT errorCode;
BOOL dataIdentical;
LoginProviderEnumerator *enumerator;
} PROVIDERUPDATERESULT;
#define NLBM_PROVIDERSUPDATED (NLBM_FIRST + 21) // wParam - not used, lParam = (LPARAM)(PROVIDERUPDATERESULT*)updateResult;
#define LoginBox_ProvidersUpdated(/*HNWD*/ __hwnd, /*LoginDownloadResult*/ __downloader, /*HRESULT*/ __errorCode, /*BOOL*/__dataIdentical, /*LoginProviderEnumerator**/ __enumerator)\
{PROVIDERUPDATERESULT __updateResult;\
__updateResult.downloader = (__downloader);\
__updateResult.errorCode = (__errorCode);\
__updateResult.dataIdentical = (__dataIdentical);\
__updateResult.enumerator = (__enumerator);\
(SendMessage((__hwnd), NLBM_PROVIDERSUPDATED, 0, (LPARAM)&(__updateResult)));}
typedef struct __IMAGECACHERESULT
{
LoginImageCache *imageCache;
ifc_omcacherecord *cacheRecord;
} IMAGECACHERESULT;
#define NLBM_IMAGECACHED (NLBM_FIRST + 22) // wParam - not used, lParam = (LPARAM)(IMAGECACHERESULT*)cacheResult;
#endif //NULLSOFT_AUTH_LOGINBOX_HEADER

View File

@@ -0,0 +1,323 @@
#include "./loginbox.h"
#include "./loginpage.h"
#include "../resource.h"
#include "../api.h"
#include <windows.h>
typedef struct __TOSREMINDERCREATEPARAM
{
HANDLE hModal;
BOOL fAnimate;
INT_PTR *pResult;
} TOSREMINDERCREATEPARAM;
typedef struct __TOSREMINDER
{
HANDLE hModal;
BOOL fAnimate;
SIZE idealSize;
INT_PTR *pResult;
} TOSREMINDER;
#define TOSREMINDER_PROP L"LoginboxTosReminderProp"
#define GetTosReminder(__hwnd) ((TOSREMINDER*)GetProp(__hwnd, TOSREMINDER_PROP))
static INT_PTR CALLBACK TosReminder_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR TosReminder_EnterModalLoop(HANDLE hExit);
HWND TosReminder_CreateWindow(HWND hParent)
{
if (NULL == hParent)
return NULL;
return WASABI_API_CREATEDIALOGPARAMW(IDD_TOSREMINDER, hParent, TosReminder_DialogProc, 0L);
}
INT_PTR TosReminder_Show(HWND hParent, INT controlId, BOOL fAnimate)
{
if (NULL == hParent)
return -1;
INT_PTR result;
TOSREMINDERCREATEPARAM param;
param.fAnimate = fAnimate;
param.pResult = &result;
param.hModal = CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == param.hModal) return -1;
HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_TOSREMINDER,
hParent, TosReminder_DialogProc, (LPARAM)&param);
if (NULL == hwnd) return -1;
SetWindowLongPtr(hwnd, GWLP_ID, controlId);
SetWindowPos(hParent, NULL, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
if (FALSE == fAnimate ||
0 == AnimateWindow(hwnd, 150, AW_ACTIVATE | AW_VER_POSITIVE | AW_SLIDE))
{
ShowWindow(hwnd, SW_SHOWNORMAL);
}
TosReminder_EnterModalLoop(param.hModal);
return result;
}
static void TosReminder_EndDialog(HWND hwnd, INT_PTR code)
{
TOSREMINDER *reminder = GetTosReminder(hwnd);
if (NULL != reminder)
{
if (NULL != reminder->pResult)
{
(*reminder->pResult) = code;
reminder->pResult = NULL;
}
if (NULL != reminder->hModal)
{
SetEvent(reminder->hModal);
reminder->hModal = NULL;
}
if (FALSE == reminder->fAnimate ||
0 == AnimateWindow(hwnd, 150, AW_HIDE | AW_VER_NEGATIVE | AW_SLIDE))
{
ShowWindow(hwnd, SW_HIDE);
}
}
DestroyWindow(hwnd);
}
static void TosReminder_UpdateLayout(HWND hwnd, BOOL fRedraw)
{
RECT clientRect;
if (FALSE == GetClientRect(hwnd, &clientRect)) return;
LONG centerX = clientRect.left + (clientRect.right - clientRect.left)/2;
LONG buttonTop = clientRect.bottom;
const INT szControls[] = {IDOK, IDCANCEL, IDC_TEXT, };
RECT controlRect;
UINT sharedFlags = SWP_NOZORDER | SWP_NOACTIVATE;
if (FALSE == fRedraw) sharedFlags |= SWP_NOREDRAW;
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
if (NULL == hdwp) return;
UINT controlFlags;
LONG x, y, cx, cy;
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
HWND hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &controlRect))
continue;
controlFlags = sharedFlags;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&controlRect, 2);
x = controlRect.left;
y = controlRect.top;
cx = controlRect.right - controlRect.left;
cy = controlRect.bottom - controlRect.top;
switch(szControls[i])
{
case IDOK:
x = centerX - cx - 8;
if (x < clientRect.left) x = clientRect.left;
y = (clientRect.bottom - 8) - cy;
if (y < clientRect.top) y = clientRect.top;
if (y < buttonTop) buttonTop = y;
break;
case IDCANCEL:
x = centerX + 8;
if ((x + cx) > clientRect.right) x = clientRect.right - cx;
y = (clientRect.bottom - 8) - cy;
if (y < clientRect.top) y = clientRect.top;
if (y < buttonTop) buttonTop = y;
break;
case IDC_TEXT:
cx = (clientRect.right - clientRect.left) - 2*x;
cy = (buttonTop - y) - 16;
break;
}
hdwp = DeferWindowPos(hdwp, hControl, NULL, x, y, cx, cy, controlFlags);
if (NULL == hdwp) return;
}
EndDeferWindowPos(hdwp);
if (FALSE != fRedraw)
{
HWND hControl = GetDlgItem(hwnd, IDC_TEXT);
if (NULL != hControl) InvalidateRect(hControl, NULL, FALSE);
}
}
static INT_PTR TosReminder_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM param)
{
TOSREMINDER *reminder = (TOSREMINDER*)malloc(sizeof(TOSREMINDER));
if (NULL == reminder)
{
DestroyWindow(hwnd);
return 0;
}
ZeroMemory(reminder, sizeof(TOSREMINDER));
SetProp(hwnd, TOSREMINDER_PROP, reminder);
TOSREMINDERCREATEPARAM *createParam = (TOSREMINDERCREATEPARAM*)param;
if (NULL != createParam)
{
reminder->fAnimate = createParam->fAnimate;
reminder->hModal = createParam->hModal;
reminder->pResult = createParam->pResult;
}
RECT windowRect;
if (FALSE != GetWindowRect(hwnd, &windowRect))
{
reminder->idealSize.cx = windowRect.right - windowRect.left;
reminder->idealSize.cy = windowRect.bottom - windowRect.top;
}
PostMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0L);
return 0;
}
static void TosReminder_OnDestroy(HWND hwnd)
{
TOSREMINDER *reminder = GetTosReminder(hwnd);
RemoveProp(hwnd, TOSREMINDER_PROP);
if (NULL == reminder)
return;
if (NULL != reminder->pResult)
{
(*reminder->pResult) = -1;
}
if (NULL != reminder->hModal)
{
SetEvent(reminder->hModal);
reminder->hModal = NULL;
}
free(reminder);
}
static void TosReminder_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp)
{
if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags))
{
TosReminder_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags));
}
}
static void TosReminder_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND hControl)
{
switch(commandId)
{
case IDOK:
TosReminder_EndDialog(hwnd, commandId);
break;
case IDCANCEL:
TosReminder_EndDialog(hwnd, commandId);
break;
}
}
static BOOL TosReminder_OnGetIdealSize(HWND hwnd, SIZE *pSize)
{
TOSREMINDER *reminder = GetTosReminder(hwnd);
if (NULL == reminder || NULL == pSize) return FALSE;
CopyMemory(pSize, &reminder->idealSize, sizeof(SIZE));
return TRUE;
}
static BOOL TosReminder_OnClose(HWND hwnd, BOOL *pfAbort)
{
TOSREMINDER *reminder = GetTosReminder(hwnd);
if (NULL != reminder) reminder->fAnimate = FALSE;
TosReminder_EndDialog(hwnd, IDCANCEL);
return TRUE;
}
static INT_PTR CALLBACK TosReminder_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: return TosReminder_OnInitDialog(hwnd, (HWND)wParam, lParam);
case WM_DESTROY: TosReminder_OnDestroy(hwnd); return 0;
case WM_WINDOWPOSCHANGED: TosReminder_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return TRUE;
case WM_COMMAND: TosReminder_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
case NLPM_GETIDEALSIZE: MSGRESULT(hwnd, TosReminder_OnGetIdealSize(hwnd, (SIZE*)lParam));
case NLPM_CLOSE: MSGRESULT(hwnd, TosReminder_OnClose(hwnd, (BOOL*)lParam));
}
return 0;
}
static BOOL TosReminder_PumpMessages()
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
{
PostQuitMessage((int)msg.wParam);
return TRUE;
}
if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return FALSE;
}
static INT_PTR TosReminder_EnterModalLoop(HANDLE hExit)
{
if (NULL == hExit)
return FALSE;
for(;;)
{
DWORD code = MsgWaitForMultipleObjectsEx(1, &hExit, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
switch(code)
{
case WAIT_FAILED:
return FALSE;
case WAIT_OBJECT_0:
return TRUE;
case (WAIT_OBJECT_0 + 1):
if (FALSE != TosReminder_PumpMessages())
return TRUE;
break;
}
}
return TRUE;
}

View File

@@ -0,0 +1,13 @@
#ifndef NULLSOFT_AUTH_LOGINBOX_TOS_REMINDER_HEADER
#define NULLSOFT_AUTH_LOGINBOX_TOS_REMINDER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
HWND TosReminder_CreateWindow(HWND hParent);
INT_PTR TosReminder_Show(HWND hParent, INT controlId, BOOL fAnimate);
#endif //NULLSOFT_AUTH_LOGINBOX_TOS_REMINDER_HEADER

View File

@@ -0,0 +1,101 @@
#ifndef NULLSOFT_AUTH_LOGINPAGE_HEADER
#define NULLSOFT_AUTH_LOGINPAGE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#define NLPM_FIRST (WM_APP + 10)
#define NLPM_PAGEFIRST (NLPM_FIRST + 40)
#define NLPM_GETLOGINDATA (NLPM_FIRST + 0) // wParam - not used, lParam = (LPARAM)(LoginData**)__ppLoginData; Return: TRUE on success.
#define LoginPage_GetData(/*HWND*/ __hwnd, /*LoginData** */ __ppLoginData)\
((BOOL)(SNDMSG((__hwnd), NLPM_GETLOGINDATA, 0, (LPARAM)(__ppLoginData))))
#define NLPM_UPDATESTATECHANGE (NLPM_FIRST + 1) // wParam - not used, lParam = (BOOL)__updateActive; Return - ignored
#define LoginPage_UpdateStateChange(/*HWND*/ __hwnd, /*BOOL*/ __updateActive)\
((BOOL)(SNDMSG((__hwnd), NLPM_UPDATESTATECHANGE, 0, (LPARAM)(__updateActive))))
#define NLPM_SETUSERNAME (NLPM_FIRST + 2) // wParam - not used, lParam = (LPARAM)(LPCWSTR)__pszUsername; Return TRUE on success
#define LoginPage_SetUsername(/*HWND*/ __hwnd, /*LPCWSTR*/ __pszUsername)\
((BOOL)(SNDMSG((__hwnd), NLPM_SETUSERNAME, 0, (LPARAM)(__pszUsername))))
#define NLPM_SETPASSWORD (NLPM_FIRST + 3) // wParam - not used, lParam = (LPARAM)(LPCWSTR)__pszPassword; Return TRUE on success
#define LoginPage_SetPassword(/*HWND*/ __hwnd, /*LPCWSTR*/ __pszPassword)\
((BOOL)(SNDMSG((__hwnd), NLPM_SETPASSWORD, 0, (LPARAM)(__pszPassword))))
#define NLPM_GETFIRSTITEM (NLPM_FIRST + 4) // wParam - not used, lParam - not used; Return HWND where you want focus to be on page create or NULL.
#define LoginPage_GetFirstItem(/*HWND*/ __hwnd)\
((HWND)(SNDMSG((__hwnd), NLPM_GETFIRSTITEM, 0, 0L)))
#define NLPM_SETTITLE (NLPM_FIRST + 5) // wParam - not used, lParam = (LPARAM)(LPCWSTR)__pszTitle; Return TRUE on success
#define LoginPage_SetTitle(/*HWND*/ __hwnd, /*LPCWSTR*/ __pszTitle)\
((BOOL)(SNDMSG((__hwnd), NLPM_SETTITLE, 0, (LPARAM)(__pszTitle))))
class LoginPage;
class LoginData;
typedef HRESULT (CALLBACK *LOGINPAGECREATOR)(HWND /*hwnd*/, HWND /*hLoginbox*/, LoginPage** /*instance*/);
class __declspec(novtable) LoginPage
{
protected:
LoginPage(HWND hwnd, HWND hLoginbox);
virtual ~LoginPage();
public:
static HWND CreatePage(HWND hLoginbox, LPCWSTR pszTemplate, HWND hParent, LPARAM param, LOGINPAGECREATOR fnCreator);
protected:
virtual void UpdateMargins();
virtual void UpdateColors();
virtual void UpdateLayout(BOOL fRedraw);
virtual BOOL GetPageRect(RECT *prc);
BOOL ShowHelp();
BOOL IsHelpAvailable();
INT GetTitleSpacing();
BOOL SetLabelText(INT controlId, LPCWSTR pszText);
protected:
virtual BOOL OnInitDialog(HWND hFocus, LPARAM param);
virtual void OnDestroy();
virtual void OnWindowPosChanged(const WINDOWPOS *pwp);
virtual void OnCommand(UINT commandId, UINT eventType, HWND hControl);
virtual BOOL OnNotify(UINT controlId, const NMHDR *pnmh);
virtual BOOL OnSetCursor(HWND hTarget, INT hitCode, INT uMsg);
virtual HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
virtual HBRUSH OnGetDialogColor(HDC hdc, HWND hControl);
virtual BOOL OnHelp(HELPINFO *phi);
virtual void OnThemeChanged();
virtual void OnSysColorChanged();
virtual BOOL OnGetLoginData(LoginData **ppLoginData);
virtual void OnUpdateStateChange(BOOL updateActive);
virtual BOOL OnSetUsername(LPCWSTR pszUsername);
virtual BOOL OnSetPassword(LPCWSTR pszPassword);
virtual HWND OnGetFirstItem();
virtual BOOL OnSetTitle(LPCWSTR pszTitle);
virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
friend static INT_PTR CALLBACK LoginPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
HWND hwnd;
HWND hLoginbox;
RECT margins;
COLORREF rgbTitle;
COLORREF rgbSecondaryText;
COLORREF rgbText;
COLORREF rgbBack;
HBRUSH hbrBack;
};
#endif //NULLSOFT_AUTH_LOGINPAGE_HEADER

View File

@@ -0,0 +1,342 @@
#include "./pageAddress.h"
#include "./dataAddress.h"
#include "./common.h"
#include "./addressEncoder.h"
#include "./addressEditbox.h"
#include "./loginGui.h"
#include "../resource.h"
#include <shlwapi.h>
#include <wininet.h>
static HRESULT CALLBACK LoginPageAddress_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginPageAddress(hwnd, hLoginbox);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPageAddress::LoginPageAddress(HWND hwnd, HWND hLoginbox)
: LoginPage(hwnd, hLoginbox)
{
HWND hEdit = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL != hEdit)
AddressEditbox_AttachWindow(hEdit);
}
LoginPageAddress::~LoginPageAddress()
{
}
HWND LoginPageAddress::CreatePage(HWND hLoginbox, HWND hParent)
{
return LoginPage::CreatePage(hLoginbox, MAKEINTRESOURCE(IDD_PAGE_ADDRESS),
hParent, NULL, LoginPageAddress_CreateInstance);
}
BOOL LoginPageAddress::OnInitDialog(HWND hFocus, LPARAM param)
{
HFONT fontEdit = NULL, fontLabel = NULL;
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
fontLabel = loginGui->GetTextFont();
fontEdit = loginGui->GetEditorFont();
loginGui->Release();
}
if (NULL != fontLabel)
{
HWND hLabel = GetDlgItem(hwnd, IDC_ADDRESS_LABEL);
if (NULL != hLabel)
SendMessage(hLabel, WM_SETFONT, (WPARAM)fontLabel, 0L);
hLabel = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL != hLabel)
SendMessage(hLabel, WM_SETFONT, (WPARAM)fontLabel, 0L);
}
if (NULL != fontEdit)
{
HWND hEdit = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL != hEdit)
SendMessage(hEdit, WM_SETFONT, (WPARAM)fontEdit, 0L);
}
LoginPage::OnInitDialog(hFocus, param);
return FALSE;
}
void LoginPageAddress::OnDestroy()
{
LoginPage::OnDestroy();
}
void LoginPageAddress::UpdateLayout(BOOL fRedraw)
{
LoginPage::UpdateLayout(fRedraw);
RECT pageRect;
GetPageRect(&pageRect);
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW;
const INT szControls[] = { IDC_ADDRESS_LABEL, IDC_ADDRESS_EDIT, IDC_MESSAGE, };
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
INT baseunitX, baseunitY;
if (FALSE == LoginBox_GetWindowBaseUnits(hwnd, &baseunitX, &baseunitY))
{
baseunitY = 13;
}
HRGN invalidRegion = CreateRectRgn(0, 0, 0, 0);
HRGN tempRegion = CreateRectRgn(0, 0, 0, 0);
HWND hControl;
INT nextTop = pageRect.top;
INT x, y, cx, cy;
RECT rect;
INT maxWidth = pageRect.right - pageRect.left;
hControl = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL != hControl)
{
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT fontControl = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, fontControl);
maxWidth = LoginBox_GetAveStrWidth(hdc, 80);
if(maxWidth > (pageRect.right - pageRect.left))
maxWidth = pageRect.right - pageRect.left;
SelectObject(hdc, fontOrig);
ReleaseDC(hControl, hdc);
}
}
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &rect)) continue;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
x = rect.left;
y = rect.top;
cx = rect.right - rect.left;
cy = rect.bottom - rect.top;
switch(szControls[i])
{
case IDC_ADDRESS_LABEL:
case IDC_MESSAGE:
x = pageRect.left;
y = nextTop;
LoginBox_GetWindowTextSize(hControl, maxWidth, &cx, &cy);
nextTop += (cy + MulDiv(2, baseunitY, 8));
break;
case IDC_ADDRESS_EDIT:
x = pageRect.left;
y = nextTop;
cy = LoginBox_GetWindowTextHeight(hControl, 0);
{
RECT r1, r2;
GetWindowRect(hControl, &r1);
SendMessage(hControl, EM_GETRECT, 0, (LPARAM)&r2);
INT t = (r1.bottom - r1.top) - (r2.bottom - r2.top);
cy += t;
}
cx = maxWidth;
nextTop += (cy + MulDiv(7, baseunitY, 8));
break;
}
if (rect.left != x || rect.top != y ||
(rect.right - rect.left) != cx || (rect.bottom - rect.top) != cy)
{
hdwp = DeferWindowPos(hdwp, hControl, NULL, x, y, cx, cy, flags);
if (NULL == hdwp) break;
if (FALSE != fRedraw)
{
SetRectRgn(tempRegion, rect.left, rect.top, rect.right, rect.bottom);
CombineRgn(invalidRegion, invalidRegion, tempRegion, RGN_OR);
SetRectRgn(tempRegion, x, y , x + cx, y + cy);
CombineRgn(invalidRegion, invalidRegion, tempRegion, RGN_OR);
}
}
}
if (NULL != hdwp)
EndDeferWindowPos(hdwp);
if (FALSE != fRedraw)
{
RedrawWindow(hwnd, NULL, invalidRegion,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN | RDW_VALIDATE);
}
if (NULL != invalidRegion)
DeleteObject(invalidRegion);
if (NULL != tempRegion)
DeleteObject(tempRegion);
}
BOOL LoginPageAddress::OnGetLoginData(LoginData **ppLoginData)
{
if (NULL == ppLoginData)
return FALSE;
HWND hEdit;
LPWSTR address;
hEdit = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL == hEdit || FAILED(LoginBox_GetWindowText(hEdit, &address, NULL)))
address = NULL;
else
{
size_t encodedMax = lstrlen(address)*2;
LPWSTR addressEncoded = LoginBox_MallocString(encodedMax);
for(;;)
{
if (FALSE == InternetCanonicalizeUrl(address, addressEncoded, (DWORD*)&encodedMax, ICU_ENCODE_PERCENT | ICU_NO_META))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
LoginBox_FreeString(addressEncoded);
addressEncoded = LoginBox_MallocString(encodedMax);
if (NULL != addressEncoded)
continue;
}
}
else
{
LoginBox_FreeString(address);
address = LoginBox_CopyString(addressEncoded);
}
break;
}
HRESULT hr;
for(;;)
{
hr = AddressEncoder_EncodeString(address, addressEncoded, &encodedMax, ICU_BROWSER_MODE);
if (ENC_E_INSUFFICIENT_BUFFER == hr)
{
LoginBox_FreeString(addressEncoded);
addressEncoded = LoginBox_MallocString(encodedMax);
if (NULL == addressEncoded)
hr = E_OUTOFMEMORY;
else
continue;
}
break;
}
if (SUCCEEDED(hr))
{
LoginBox_FreeString(address);
address = addressEncoded;
addressEncoded = NULL;
}
else
LoginBox_FreeString(addressEncoded);
}
HRESULT hr = LoginDataAddress::CreateInstance(NULL, hwnd, hLoginbox,
address, (LoginDataAddress**)ppLoginData);
LoginBox_FreeString(address);
return SUCCEEDED(hr);
}
BOOL LoginPageAddress::OnSetUsername(LPCWSTR pszUsername)
{
HWND hEdit = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL == hEdit) return FALSE;
if (NULL == pszUsername || L'\0' == *pszUsername)
return FALSE;
INT cchLen = lstrlen(pszUsername);
INT f, l;
SNDMSG(hEdit, EM_GETSEL, (WPARAM)&f, (LPARAM)&l);
if (f == l) return FALSE;
SNDMSG(hEdit, EM_REPLACESEL, FALSE, (LPARAM)pszUsername);
SNDMSG(hEdit, EM_SETSEL, (WPARAM)f, (LPARAM)f + cchLen);
return TRUE;
}
HBRUSH LoginPageAddress::OnGetStaticColor(HDC hdc, HWND hControl)
{
INT_PTR controlId = (INT_PTR)GetWindowLongPtr(hControl, GWLP_ID);
switch(controlId)
{
case IDC_MESSAGE:
SetTextColor(hdc, rgbSecondaryText);
SetBkColor(hdc, rgbBack);
return hbrBack;
}
return LoginPage::OnGetStaticColor(hdc, hControl);
}
BOOL LoginPageAddress::OnSetAddress(LPCWSTR pszAddress, BOOL replaceUsername)
{
HWND hEdit = GetDlgItem(hwnd, IDC_ADDRESS_EDIT);
if (NULL == hEdit) return FALSE;
BOOL succeeded;
LPWSTR addressDecoded;
if (SUCCEEDED(AddressEncoder_DecodeString(pszAddress, &addressDecoded)))
{
succeeded = (BOOL)SNDMSG(hEdit, WM_SETTEXT, 0, (LPARAM)addressDecoded);
LoginBox_FreeString(addressDecoded);
}
else
succeeded = (BOOL)SNDMSG(hEdit, WM_SETTEXT, 0, (LPARAM)pszAddress);
return succeeded;
}
BOOL LoginPageAddress::OnSetAddressTitle(LPCWSTR pszTitle)
{
return SetLabelText(IDC_ADDRESS_LABEL, pszTitle);
}
BOOL LoginPageAddress::OnSetMessage(LPCWSTR pszMessage)
{
HWND hLabel = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL == hLabel) return FALSE;
return SetWindowText(hLabel, pszMessage);
}
INT_PTR LoginPageAddress::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case NLPAM_SETADDRESS: MSGRESULT(hwnd, OnSetAddress((LPCWSTR)lParam, (BOOL)wParam));
case NLPAM_SETADDRESSTITLE: MSGRESULT(hwnd, OnSetAddressTitle((LPCWSTR)lParam));
case NLPAM_SETMESSAGE: MSGRESULT(hwnd, OnSetMessage((LPCWSTR)lParam));
}
return __super::DialogProc(uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,58 @@
#ifndef NULLSOFT_AUTH_LOGIN_PAGE_ADDRESS_HEADER
#define NULLSOFT_AUTH_LOGIN_PAGE_ADDRESS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPage.h"
#define NLPAM_FIRST (NLPM_PAGEFIRST + 0)
#define NLPAM_SETADDRESS (NLPAM_FIRST + 0) //wParam = (WPARAM)(BOOL)replaceUsername, lParam = (LPARAM)(LPCWSTR)pszAddress; Return - TRUE on succeess.
#define LoginPageAddress_SetAddress(/*HWND*/ __hwnd, /*LPCWSTR*/ __address, /*BOOL*/ __replaceUsername)\
((BOOL)SNDMSG((__hwnd), NLPAM_SETADDRESS, (WPARAM)(__replaceUsername), (LPARAM)(__address)))
#define NLPAM_SETADDRESSTITLE (NLPAM_FIRST + 1) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszAddressTitle; Return - TRUE on succeess.
#define LoginPageAddress_SetAddressTitle(/*HWND*/ __hwnd, /*LPCWSTR*/ __addressTitle)\
((BOOL)SNDMSG((__hwnd), NLPAM_SETADDRESSTITLE, 0, (LPARAM)(__addressTitle)))
#define NLPAM_SETMESSAGE (NLPAM_FIRST + 2) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszMessage; Return - TRUE on succeess.
#define LoginPageAddress_SetMessage(/*HWND*/ __hwnd, /*LPCWSTR*/ __pszMessage)\
((BOOL)SNDMSG((__hwnd), NLPAM_SETMESSAGE, 0, (LPARAM)(__pszMessage)))
class LoginPageAddress : public LoginPage
{
protected:
LoginPageAddress(HWND hwnd, HWND hLoginbox);
~LoginPageAddress();
public:
static HWND CreatePage(HWND hLoginbox, HWND hParent);
protected:
void UpdateLayout(BOOL fRedraw);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
void OnDestroy();
BOOL OnGetLoginData(LoginData **ppLoginData);
BOOL OnSetUsername(LPCWSTR pszUsername);
HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
BOOL OnSetAddress(LPCWSTR pszAddress, BOOL replaceUsername);
BOOL OnSetAddressTitle(LPCWSTR pszTitle);
BOOL OnSetMessage(LPCWSTR pszMessage);
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
friend static HRESULT CALLBACK LoginPageAddress_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance);
};
#endif //NULLSOFT_AUTH_LOGIN_PAGE_ADDRESS_HEADER

View File

@@ -0,0 +1,416 @@
#include "./pageCredentials.h"
#include "./dataCredentials.h"
#include "./common.h"
#include "./loginGui.h"
#include "../../winamp/commandLink.h"
#include "../resource.h"
#include <commctrl.h>
static HRESULT CALLBACK LoginPageCredentials_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginPageCredentials(hwnd, hLoginbox);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPageCredentials::LoginPageCredentials(HWND hwnd, HWND hLoginbox)
: LoginPage(hwnd, hLoginbox), accountRecoverUrl(NULL), accountCreateUrl(NULL)
{
}
LoginPageCredentials::~LoginPageCredentials()
{
LoginBox_FreeString(accountRecoverUrl);
LoginBox_FreeString(accountCreateUrl);
}
HWND LoginPageCredentials::CreatePage(HWND hLoginbox, HWND hParent)
{
return LoginPage::CreatePage(hLoginbox, MAKEINTRESOURCE(IDD_PAGE_CREDENTIALS),
hParent, NULL, LoginPageCredentials_CreateInstance);
}
void LoginPageCredentials::UpdateLayout(BOOL fRedraw)
{
LoginPage::UpdateLayout(fRedraw);
RECT pageRect;
if (FALSE == GetPageRect(&pageRect))
return;
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
const INT szControls[] = { IDC_USERNAME_LABEL, IDC_USERNAME, IDC_PASSWORD_LABEL, IDC_PASSWORD};
const INT szLinks[] = { IDC_CREATE_ACCOUNT, IDC_RECOVER_ACCOUNT };
INT baseunitX, baseunitY;
if (FALSE == LoginBox_GetWindowBaseUnits(hwnd, &baseunitX, &baseunitY))
{
baseunitX = 6;
baseunitY = 13;
}
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls) + ARRAYSIZE(szLinks));
HWND hControl;
INT cx, cy, x, y;
INT editWidth = 0;
INT column1Width = 0;
INT column2Width = 0;
INT columnSpace = MulDiv(7, baseunitX, 4);
SIZE sizeLink;
RECT linkMargins;
// column 1 width
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl) continue;
switch(szControls[i])
{
case IDC_USERNAME_LABEL:
case IDC_PASSWORD_LABEL:
if (FALSE != (LoginBox_GetWindowTextSize(hControl, pageRect.right - pageRect.left, &cx, &cy)) &&
cx > column1Width)
{
column1Width = cx;
}
break;
case IDC_USERNAME:
case IDC_PASSWORD:
if (0 == editWidth)
{
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT fontControl = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, fontControl);
editWidth = LoginBox_GetAveStrWidth(hdc, 28);
SelectObject(hdc, fontOrig);
ReleaseDC(hControl, hdc);
}
if (0 != editWidth)
{
LRESULT editMargins = SendMessage(hControl, EM_GETMARGINS, 0,0L);
editWidth += (LOWORD(editMargins) + HIWORD(editMargins));
}
}
if (editWidth > column1Width)
column1Width = editWidth;
break;
}
}
// column 2 width
for (INT i = 0; i < ARRAYSIZE(szLinks); i++)
{
hControl = GetDlgItem(hwnd, szLinks[i]);
if (NULL != hControl &&
0 != (WS_VISIBLE & GetWindowStyle(hControl)) &&
FALSE != CommandLink_GetIdealSize(hControl, &sizeLink))
{
if (FALSE != CommandLink_GetMargins(hControl, &linkMargins))
sizeLink.cx -= linkMargins.right;
if (column2Width < sizeLink.cx)
column2Width = sizeLink.cx;
}
}
BOOL multiColumnLayout;
if (column2Width > 0 &&
(column1Width + columnSpace + column2Width) <= (pageRect.right - pageRect.left))
{
multiColumnLayout = TRUE;
}
else
{
multiColumnLayout = FALSE;
}
INT nextTop = 0;
if (column2Width != 0)
{
if(FALSE == multiColumnLayout)
nextTop = pageRect.top - GetTitleSpacing()/2;
else
{
nextTop = pageRect.top;
HWND hLabel = GetDlgItem(hwnd, IDC_USERNAME_LABEL);
INT offsetY = (NULL != hLabel) ? LoginBox_GetWindowTextHeight(hLabel, 0) : 0;
if (0 == offsetY) offsetY = baseunitY;
nextTop += (offsetY - 1);
}
for (INT i = 0; i < ARRAYSIZE(szLinks); i++)
{
hControl = GetDlgItem(hwnd, szLinks[i]);
if (NULL == hControl || 0 == (WS_VISIBLE & GetWindowStyle(hControl)))
continue;
if (FALSE == CommandLink_GetIdealSize(hControl, &sizeLink))
ZeroMemory(&sizeLink, sizeof(SIZE));
x = pageRect.right - sizeLink.cx;
if (x < pageRect.left) x = pageRect.left;
if (FALSE != CommandLink_GetMargins(hControl, &linkMargins))
x += linkMargins.right;
if (i == 0)
nextTop -= linkMargins.top;
hdwp = DeferWindowPos(hdwp, hControl, NULL, x, nextTop, sizeLink.cx, sizeLink.cy, flags);
if (NULL == hdwp) break;
nextTop += sizeLink.cy;
if (i != (ARRAYSIZE(szLinks) -1))
nextTop += MulDiv(1, baseunitY, 8);
}
}
if (FALSE != multiColumnLayout || 0 == column2Width)
nextTop = pageRect.top;
else
nextTop += MulDiv(2, baseunitY, 8);
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl) continue;
switch(szControls[i])
{
case IDC_USERNAME_LABEL:
case IDC_PASSWORD_LABEL:
x = pageRect.left;
y = nextTop;
LoginBox_GetWindowTextSize(hControl, pageRect.right - pageRect.left, &cx, &cy);
nextTop += (cy + MulDiv(2, baseunitY, 8));
if (cx > column1Width)
cx = column1Width;
break;
case IDC_USERNAME:
case IDC_PASSWORD:
x = pageRect.left;
y = nextTop;
cy = LoginBox_GetWindowTextHeight(hControl, 0);
{
RECT r1, r2;
GetWindowRect(hControl, &r1);
SendMessage(hControl, EM_GETRECT, 0, (LPARAM)&r2);
INT t = (r1.bottom - r1.top) - (r2.bottom - r2.top);
cy += t;
}
nextTop += (cy + MulDiv(4, baseunitY, 8));
cx = column1Width;
if ((x + cx) > pageRect.right)
cx = pageRect.right - x;
break;
}
hdwp = DeferWindowPos(hdwp, hControl, NULL, x, y, cx, cy, flags);
if (NULL == hdwp) break;
}
if (NULL != hdwp)
EndDeferWindowPos(hdwp);
}
BOOL LoginPageCredentials::OnInitDialog(HWND hFocus, LPARAM param)
{
HWND hControl;
const INT szLinks[] = { IDC_CREATE_ACCOUNT, IDC_RECOVER_ACCOUNT };
for (INT i = 0; i < ARRAYSIZE(szLinks); i++)
{
hControl = GetDlgItem(hwnd, szLinks[i]);
if (NULL == hControl) continue;
RECT linkMargins;
SetRect(&linkMargins, 2, 0, 2, 2);
MapDialogRect(hwnd, &linkMargins);
CommandLink_SetMargins(hControl, &linkMargins);
}
HFONT fontLabel = NULL, fontEdit = NULL;
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
fontLabel = loginGui->GetTextFont();
fontEdit = loginGui->GetEditorFont();
loginGui->Release();
}
if (NULL != fontLabel)
{
const INT szLabels[] = { IDC_USERNAME_LABEL, IDC_PASSWORD_LABEL};
for (INT i = 0; i < ARRAYSIZE(szLabels); i++)
{
hControl = GetDlgItem(hwnd, szLabels[i]);
if (NULL != hControl)
SendMessage(hControl, WM_SETFONT, (WPARAM)fontLabel, 0L);
}
}
if (NULL != fontEdit)
{
const INT szEdits[] = { IDC_USERNAME, IDC_PASSWORD};
for (INT i = 0; i < ARRAYSIZE(szEdits); i++)
{
hControl = GetDlgItem(hwnd, szEdits[i]);
if (NULL != hControl)
SendMessage(hControl, WM_SETFONT, (WPARAM)fontEdit, 0L);
}
}
LoginPage::OnInitDialog(hFocus, param);
return FALSE;
}
BOOL LoginPageCredentials::OnNotify(UINT controlId, const NMHDR *pnmh)
{
switch(controlId)
{
case IDC_CREATE_ACCOUNT:
if (pnmh->code == NM_CLICK && NULL != accountCreateUrl && L'\0' != *accountCreateUrl)
LoginBox_OpenUrl(hwnd, accountCreateUrl, TRUE);
return TRUE;
case IDC_RECOVER_ACCOUNT:
if (pnmh->code == NM_CLICK && NULL != accountRecoverUrl && L'\0' != *accountRecoverUrl)
LoginBox_OpenUrl(hwnd, accountRecoverUrl, TRUE);
return TRUE;
}
return LoginPage::OnNotify(controlId, pnmh);
}
BOOL LoginPageCredentials::OnGetLoginData(LoginData **ppLoginData)
{
if (NULL == ppLoginData)
return FALSE;
HWND hEdit;
LPWSTR username, password;
hEdit = GetDlgItem(hwnd, IDC_USERNAME);
if (NULL == hEdit || FAILED(LoginBox_GetWindowText(hEdit, &username, NULL)))
username = NULL;
hEdit = GetDlgItem(hwnd, IDC_PASSWORD);
if (NULL == hEdit || FAILED(LoginBox_GetWindowText(hEdit, &password, NULL)))
password = NULL;
HRESULT hr = LoginDataCredentials::CreateInstance(NULL, hwnd, hLoginbox,
username, password, (LoginDataCredentials**)ppLoginData);
LoginBox_FreeStringSecure(username);
LoginBox_FreeStringSecure(password);
return SUCCEEDED(hr);
}
void LoginPageCredentials::OnSetAccountRecoverUrl(LPCWSTR pszUrl)
{
LoginBox_FreeString(accountRecoverUrl);
accountRecoverUrl = LoginBox_CopyString(pszUrl);
HWND hLink = GetDlgItem(hwnd, IDC_RECOVER_ACCOUNT);
if (NULL != hLink)
{
INT showWindow = (NULL != accountRecoverUrl && S_OK == IsValidURL(NULL, accountRecoverUrl, 0)) ? SW_SHOWNA : SW_HIDE;
ShowWindow(hLink, showWindow);
}
}
void LoginPageCredentials::OnSetAccountCreateUrl(LPCWSTR pszUrl)
{
LoginBox_FreeString(accountCreateUrl);
accountCreateUrl = LoginBox_CopyString(pszUrl);
HWND hLink = GetDlgItem(hwnd, IDC_CREATE_ACCOUNT);
if (NULL != hLink)
{
INT showWindow = (NULL != accountCreateUrl && S_OK == IsValidURL(NULL, accountCreateUrl, 0)) ? SW_SHOWNA : SW_HIDE;
ShowWindow(hLink, showWindow);
}
}
void LoginPageCredentials::OnSetUsernameLabel(LPCWSTR pszLabel)
{
SetLabelText(IDC_USERNAME_LABEL, pszLabel);
}
void LoginPageCredentials::OnSetPasswordLabel(LPCWSTR pszLabel)
{
SetLabelText(IDC_PASSWORD_LABEL, pszLabel);
}
BOOL LoginPageCredentials::OnSetUsername(LPCWSTR pszUsername)
{
HWND hEdit = GetDlgItem(hwnd, IDC_USERNAME);
if (NULL == hEdit) return FALSE;
BOOL result = (BOOL)SNDMSG(hEdit, WM_SETTEXT, 0, (LPARAM)pszUsername);
if (FALSE != result)
{
SNDMSG(hEdit, EM_SETSEL, 0, -1);
}
return result;
}
BOOL LoginPageCredentials::OnSetPassword(LPCWSTR pszPassword)
{
HWND hEdit = GetDlgItem(hwnd, IDC_PASSWORD);
if (NULL == hEdit) return FALSE;
BOOL result = (BOOL)SNDMSG(hEdit, WM_SETTEXT, 0, (LPARAM)pszPassword);
if (FALSE != result)
{
SNDMSG(hEdit, EM_SETSEL, 0, -1);
}
return result;
}
HWND LoginPageCredentials::OnGetFirstItem()
{
HWND hEdit = GetDlgItem(hwnd, IDC_USERNAME);
if (NULL != hEdit && (WS_VISIBLE == ((WS_VISIBLE | WS_DISABLED) & GetWindowStyle(hEdit))))
return hEdit;
return LoginPage::OnGetFirstItem();
}
INT_PTR LoginPageCredentials::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case NLPCM_SETACCOUNTRECOVERURL: OnSetAccountRecoverUrl((LPCWSTR)lParam); return TRUE;
case NLPCM_SETACCOUNTCREATEURL: OnSetAccountCreateUrl((LPCWSTR)lParam); return TRUE;
case NLPCM_SETUSERNAMELABEL: OnSetUsernameLabel((LPCWSTR)lParam); return TRUE;
case NLPCM_SETPASSWORDLABEL: OnSetPasswordLabel((LPCWSTR)lParam); return TRUE;
}
return __super::DialogProc(uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,66 @@
#ifndef NULLSOFT_AUTH_LOGIN_PAGE_CREDENTIALS_HEADER
#define NULLSOFT_AUTH_LOGIN_PAGE_CREDENTIALS_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPage.h"
#define NLPCM_FIRST (NLPM_PAGEFIRST + 0)
#define NLPCM_SETACCOUNTRECOVERURL (NLPCM_FIRST + 1) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszAccountRecoverUrl; Return - no return value.
#define LoginPageCredentials_SetAccountRecoverUrl(/*HWND*/ __hwnd, /*LPCWSTR*/ __url)\
(SNDMSG((__hwnd), NLPCM_SETACCOUNTRECOVERURL, 0, (LPARAM)(__url)))
#define NLPCM_SETACCOUNTCREATEURL (NLPCM_FIRST + 2) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszAccountCreateUrl; Return - no return value.
#define LoginPageCredentials_SetAccountCreateUrl(/*HWND*/ __hwnd, /*LPCWSTR*/ __url)\
(SNDMSG((__hwnd), NLPCM_SETACCOUNTCREATEURL, 0, (LPARAM)(__url)))
#define NLPCM_SETUSERNAMELABEL (NLPCM_FIRST + 3) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszUsernameLabel; Return - no return value.
#define LoginPageCredentials_SetUsernameLabel(/*HWND*/ __hwnd, /*LPCWSTR*/ __label)\
(SNDMSG((__hwnd), NLPCM_SETUSERNAMELABEL, 0, (LPARAM)(__label)))
#define NLPCM_SETPASSWORDLABEL (NLPCM_FIRST + 4) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszPasswordLabel; Return - no return value.
#define LoginPageCredentials_SetPasswordLabel(/*HWND*/ __hwnd, /*LPCWSTR*/ __label)\
(SNDMSG((__hwnd), NLPCM_SETPASSWORDLABEL, 0, (LPARAM)(__label)))
class LoginPageCredentials : public LoginPage
{
protected:
LoginPageCredentials(HWND hwnd, HWND hLoginbox);
~LoginPageCredentials();
public:
static HWND CreatePage(HWND hLoginbox, HWND hParent);
protected:
void UpdateLayout(BOOL fRedraw);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
BOOL OnNotify(UINT controlId, const NMHDR *pnmh);
BOOL OnGetLoginData(LoginData **ppLoginData);
BOOL OnSetUsername(LPCWSTR pszUsername);
BOOL OnSetPassword(LPCWSTR pszPassword);
HWND OnGetFirstItem();
void OnSetAccountRecoverUrl(LPCWSTR pszUrl);
void OnSetAccountCreateUrl(LPCWSTR pszUrl);
void OnSetUsernameLabel(LPCWSTR pszLabel);
void OnSetPasswordLabel(LPCWSTR pszLabel);
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
friend static HRESULT CALLBACK LoginPageCredentials_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance);
protected:
LPWSTR accountRecoverUrl;
LPWSTR accountCreateUrl;
};
#endif //NULLSOFT_AUTH_LOGIN_PAGE_CREDENTIALS_HEADER

View File

@@ -0,0 +1,171 @@
#include "./pageEmpty.h"
#include "./loginBox.h"
#include "./common.h"
#include "../resource.h"
static HRESULT CALLBACK LoginPageEmpty_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginPageEmpty(hwnd, hLoginbox);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPageEmpty::LoginPageEmpty(HWND hwnd, HWND hLoginbox)
: LoginPage(hwnd, hLoginbox)
{
}
LoginPageEmpty::~LoginPageEmpty()
{
}
HWND LoginPageEmpty::CreatePage(HWND hLoginbox, HWND hParent)
{
return LoginPage::CreatePage(hLoginbox, MAKEINTRESOURCE(IDD_PAGE_EMPTY),
hParent, NULL, LoginPageEmpty_CreateInstance);
}
BOOL LoginPageEmpty::OnInitDialog(HWND hFocus, LPARAM param)
{
if (NULL != hLoginbox)
{
BOOL updateActive = LoginBox_GetUpdateState(hLoginbox);
EnableCheckButton(FALSE == updateActive);
}
LoginPage::OnInitDialog(hFocus, param);
return FALSE;
}
void LoginPageEmpty::OnCommand(UINT commandId, UINT eventType, HWND hControl)
{
switch(commandId)
{
case IDC_CHECKNOW:
if (BN_CLICKED == eventType && NULL != hLoginbox)
LoginBox_UpdateProviders(hLoginbox, TRUE);
break;
}
LoginPage::OnCommand(commandId, eventType, hControl);
}
void LoginPageEmpty::UpdateLayout(BOOL fRedraw)
{
LoginPage::UpdateLayout(fRedraw);
RECT clientRect;
GetClientRect(hwnd, &clientRect);
RECT offsetRect;
SetRect(&offsetRect, 2, 4, 4, 22);
MapDialogRect(hwnd, &offsetRect);
clientRect.left += offsetRect.left;
clientRect.top += offsetRect.top;
clientRect.right -= offsetRect.right;
clientRect.bottom -= offsetRect.bottom;
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
const INT szControls[] = { IDC_MESSAGE, IDC_CHECKNOW, IDC_CHECK_STATUS};
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
RECT rect;
LONG clientTop = clientRect.top;
LONG left, top = clientRect.top;
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
HWND hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &rect)) continue;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
switch(szControls[i])
{
case IDC_MESSAGE:
top = clientRect.top + ((clientRect.bottom - clientRect.top) - (rect.bottom - rect.top))/2;
left = clientRect.left + ((clientRect.right - clientRect.left) - (rect.right - rect.left))/2;
OffsetRect(&rect, left - rect.left, top - rect.top);
clientTop = rect.bottom;
break;
case IDC_CHECKNOW:
top = clientTop + 2*offsetRect.top;
left = clientRect.left + ((clientRect.right - clientRect.left) - (rect.right - rect.left))/2;
OffsetRect(&rect, left - rect.left, top - rect.top);
break;
case IDC_CHECK_STATUS:
top = clientTop + offsetRect.top;
left = clientRect.left + ((clientRect.right - clientRect.left) - (rect.right - rect.left))/2;
OffsetRect(&rect, left - rect.left, top - rect.top);
break;
}
hdwp = DeferWindowPos(hdwp, hControl, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags);
if (NULL == hdwp) break;
}
if (NULL != hdwp)
EndDeferWindowPos(hdwp);
}
HBRUSH LoginPageEmpty::OnGetStaticColor(HDC hdc, HWND hControl)
{
INT_PTR controlId = (INT_PTR)GetWindowLongPtr(hControl, GWLP_ID);
switch(controlId)
{
case IDC_MESSAGE:
case IDC_CHECK_STATUS:
SetTextColor(hdc, rgbSecondaryText);
SetBkColor(hdc, rgbBack);
return hbrBack;
}
return LoginPage::OnGetStaticColor(hdc, hControl);
}
BOOL LoginPageEmpty::OnGetLoginData(LoginData **ppLoginData)
{
return FALSE;
}
void LoginPageEmpty::OnUpdateStateChange(BOOL updateActive)
{
EnableCheckButton(FALSE == updateActive);
}
void LoginPageEmpty::EnableCheckButton(BOOL fEnable)
{
HWND hButton = GetDlgItem(hwnd, IDC_CHECKNOW);
HWND hStatus = GetDlgItem(hwnd, IDC_CHECK_STATUS);
if (FALSE != fEnable)
{
if (NULL != hStatus)
ShowWindow(hStatus, SW_HIDE);
if (NULL != hButton)
{
EnableWindow(hButton, TRUE);
ShowWindow(hButton, SW_SHOWNA);
}
}
else
{
if (NULL != hButton)
{
if (NULL != hStatus)
ShowWindow(hButton, SW_HIDE);
EnableWindow(hButton, FALSE);
}
if (NULL != hStatus)
ShowWindow(hStatus, SW_SHOWNA);
}
}

View File

@@ -0,0 +1,37 @@
#ifndef NULLSOFT_AUTH_LOGIN_PAGE_EMPTY_HEADER
#define NULLSOFT_AUTH_LOGIN_PAGE_EMPTY_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPage.h"
class LoginPageEmpty: public LoginPage
{
protected:
LoginPageEmpty(HWND hwnd, HWND hLoginbox);
~LoginPageEmpty();
public:
static HWND CreatePage(HWND hLoginbox, HWND hParent);
protected:
void UpdateLayout(BOOL fRedraw);
void EnableCheckButton(BOOL fEnable);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
void OnCommand(UINT commandId, UINT eventType, HWND hControl);
BOOL OnGetLoginData(LoginData **ppLoginData);
void OnUpdateStateChange(BOOL updateActive);
HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
private:
friend static HRESULT CALLBACK LoginPageEmpty_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance);
};
#endif //NULLSOFT_AUTH_LOGIN_PAGE_EMPTY_HEADER

View File

@@ -0,0 +1,98 @@
#include "./pageError.h"
#include "./loginBox.h"
#include "./common.h"
#include "../resource.h"
static HRESULT CALLBACK LoginPageError_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginPageError(hwnd, hLoginbox);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPageError::LoginPageError(HWND hwnd, HWND hLoginbox)
: LoginPage(hwnd, hLoginbox)
{
}
LoginPageError::~LoginPageError()
{
}
HWND LoginPageError::CreatePage(HWND hLoginbox, HWND hParent)
{
return LoginPage::CreatePage(hLoginbox, MAKEINTRESOURCE(IDD_PAGE_ERROR),
hParent, NULL, LoginPageError_CreateInstance);
}
void LoginPageError::UpdateLayout(BOOL fRedraw)
{
LoginPage::UpdateLayout(fRedraw);
RECT clientRect;
GetClientRect(hwnd, &clientRect);
RECT offsetRect;
SetRect(&offsetRect, 2, 4, 4, 22);
MapDialogRect(hwnd, &offsetRect);
clientRect.left += offsetRect.left;
clientRect.top += offsetRect.top;
clientRect.right -= offsetRect.right;
clientRect.bottom -= offsetRect.bottom;
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
const INT szControls[] = { IDC_MESSAGE, };
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls));
RECT rect;
LONG left, top = clientRect.top;
for (INT i = 0; i < ARRAYSIZE(szControls); i++)
{
HWND hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &rect)) continue;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
switch(szControls[i])
{
case IDC_MESSAGE:
top = clientRect.top + ((clientRect.bottom - clientRect.top) - (rect.bottom - rect.top))/2;
left = clientRect.left + ((clientRect.right - clientRect.left) - (rect.right - rect.left))/2;
OffsetRect(&rect, left - rect.left, top - rect.top);
break;
}
hdwp = DeferWindowPos(hdwp, hControl, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags);
if (NULL == hdwp) break;
}
if (NULL != hdwp)
EndDeferWindowPos(hdwp);
}
HBRUSH LoginPageError::OnGetStaticColor(HDC hdc, HWND hControl)
{
INT_PTR controlId = (INT_PTR)GetWindowLongPtr(hControl, GWLP_ID);
switch(controlId)
{
case IDC_MESSAGE:
SetTextColor(hdc, rgbSecondaryText);
SetBkColor(hdc, rgbBack);
return hbrBack;
}
return LoginPage::OnGetStaticColor(hdc, hControl);
}
BOOL LoginPageError::OnGetLoginData(LoginData **ppLoginData)
{
return FALSE;
}

View File

@@ -0,0 +1,31 @@
#ifndef NULLSOFT_AUTH_LOGIN_PAGE_ERROR_HEADER
#define NULLSOFT_AUTH_LOGIN_PAGE_ERROR_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPage.h"
class LoginPageError : public LoginPage
{
protected:
LoginPageError(HWND hwnd, HWND hLoginbox);
~LoginPageError();
public:
static HWND CreatePage(HWND hLoginbox, HWND hParent);
protected:
void UpdateLayout(BOOL fRedraw);
HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
BOOL OnGetLoginData(LoginData **ppLoginData);
private:
friend static HRESULT CALLBACK LoginPageError_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance);
};
#endif //NULLSOFT_AUTH_LOGIN_PAGE_ERROR_HEADER

View File

@@ -0,0 +1,131 @@
#include "./pageInfo.h"
#include "./common.h"
#include "./loginGui.h"
#include "../resource.h"
static HRESULT CALLBACK LoginPageInfo_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd || NULL == hLoginbox) return E_INVALIDARG;
*instance = new LoginPageInfo(hwnd, hLoginbox);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPageInfo::LoginPageInfo(HWND hwnd, HWND hLoginbox)
: LoginPage(hwnd, hLoginbox)
{
}
LoginPageInfo::~LoginPageInfo()
{
}
HWND LoginPageInfo::CreatePage(HWND hLoginbox, HWND hParent)
{
return LoginPage::CreatePage(hLoginbox, MAKEINTRESOURCE(IDD_PAGE_INFO),
hParent, NULL, LoginPageInfo_CreateInstance);
}
void LoginPageInfo::UpdateLayout(BOOL fRedraw)
{
LoginPage::UpdateLayout(fRedraw);
RECT pageRect;
if (FALSE == GetPageRect(&pageRect))
return;
HWND hMessage = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL == hMessage) return;
INT cx, cy;
cx = pageRect.right - pageRect.left;
HDC hdc = GetDCEx(hMessage, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
HFONT fontControl = (HFONT)SendMessage(hMessage, WM_GETFONT, 0, 0L);
HFONT fontOrig = (HFONT)SelectObject(hdc, fontControl);
INT maxWidth = LoginBox_GetAveStrWidth(hdc, 80);
if (cx > maxWidth) cx = maxWidth;
SelectObject(hdc, fontOrig);
ReleaseDC(hMessage, hdc);
}
LoginBox_GetWindowTextSize(hMessage, cx, &cx, &cy);
if(cy > (pageRect.bottom - pageRect.top))
cy = pageRect.bottom - pageRect.top;
RECT messageRect;
GetWindowRect(hMessage, &messageRect);
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&messageRect, 2);
if (messageRect.left != pageRect.left ||
messageRect.top != pageRect.top ||
(messageRect.right - messageRect.left) != cx ||
(messageRect.bottom - messageRect.top) != cy)
{
SetWindowPos(hMessage, NULL, pageRect.left, pageRect.top, cx, cy,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
if (FALSE != fRedraw)
{
HRGN rgn1 = CreateRectRgnIndirect(&messageRect);
HRGN rgn2 = CreateRectRgn(pageRect.left, pageRect.top, pageRect.left + cx, pageRect.top + cy);
CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
RedrawWindow(hwnd, NULL, rgn1, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ERASENOW | RDW_VALIDATE | RDW_ALLCHILDREN);
DeleteObject(rgn1);
DeleteObject(rgn2);
}
}
}
BOOL LoginPageInfo::OnInitDialog(HWND hFocus, LPARAM param)
{
HFONT fontText = NULL;
LoginGuiObject *loginGui;
if (SUCCEEDED(LoginGuiObject::QueryInstance(&loginGui)))
{
fontText = loginGui->GetTextFont();
loginGui->Release();
}
if (NULL != fontText)
{
HWND hMessage = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL != hMessage)
SendMessage(hMessage, WM_SETFONT, (WPARAM)fontText, 0L);
}
LoginPage::OnInitDialog(hFocus, param);
return FALSE;
}
void LoginPageInfo::OnSetMessage(LPCWSTR pszMessage)
{
HWND hMessage = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL != hMessage)
{
SetWindowText(hMessage, pszMessage);
INT showWindow = (NULL != pszMessage && L'\0' != *pszMessage) ? SW_SHOWNA : SW_HIDE;
ShowWindow(hMessage, showWindow);
}
}
INT_PTR LoginPageInfo::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case NLPIM_SETMESSAGE: OnSetMessage((LPCWSTR)lParam); return TRUE;
}
return __super::DialogProc(uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,41 @@
#ifndef NULLSOFT_AUTH_LOGIN_PAGE_INFO_HEADER
#define NULLSOFT_AUTH_LOGIN_PAGE_INFO_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPage.h"
#define NLPIM_FIRST (NLPM_PAGEFIRST + 0)
#define NLPIM_SETMESSAGE (NLPIM_FIRST + 0) //wParam - not used, lParam = (LPARAM)(LPCWSTR)pszMessage; Return - no return value.
#define LoginPageInfo_SetMessage(/*HWND*/ __hwnd, /*LPCWSTR*/ __pszMessage)\
(SNDMSG((__hwnd), NLPIM_SETMESSAGE, 0, (LPARAM)(__pszMessage)))
class LoginPageInfo: public LoginPage
{
protected:
LoginPageInfo(HWND hwnd, HWND hLoginbox);
~LoginPageInfo();
public:
static HWND CreatePage(HWND hLoginbox, HWND hParent);
protected:
void UpdateLayout(BOOL fRedraw);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
void OnSetMessage(LPCWSTR pszMessage);
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
friend static HRESULT CALLBACK LoginPageInfo_CreateInstance(HWND hwnd, HWND hLoginbox, LoginPage **instance);
};
#endif //NULLSOFT_AUTH_LOGIN_PAGE_INFO_HEADER

16
Src/auth/Loginbox/png.rc Normal file
View File

@@ -0,0 +1,16 @@
#include "../resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// Data
//
IDR_POPUPBORDER_IMAGE RCDATA
".\\resources\\popupBorder.png"
IDR_NOTIFIERICONS_IMAGE RCDATA
".\\resources\\notifierIcons.png"
IDR_SELECTIONFRAME_IMAGE RCDATA
".\\resources\\selection.png"
IDR_ARROW_IMAGE RCDATA
".\\resources\\arrow.png"

View File

@@ -0,0 +1,567 @@
#include "./popupAgreement.h"
#include "./loginNotifier.h"
#include "./loginProvider.h"
#include "./common.h"
#include "../resource.h"
#include "../api.h"
#include "../../winamp/commandLink.h"
#include <windows.h>
#include <commctrl.h>
#include <strsafe.h>
#define LINK_TOS 0
#define STATIC_AND 1
#define LINK_PRIVACY 2
#define IDC_AOL 11000
#define IDC_AOL_TOS (IDC_AOL + LINK_TOS)
#define IDC_AOL_AND (IDC_AOL + STATIC_AND)
#define IDC_AOL_PRIVACY (IDC_AOL + LINK_PRIVACY)
#define IDC_3DPARTY 11010
#define IDC_3DPARTY_TOS (IDC_3DPARTY + LINK_TOS)
#define IDC_3DPARTY_AND (IDC_3DPARTY + STATIC_AND)
#define IDC_3DPARTY_PRIVACY (IDC_3DPARTY + LINK_PRIVACY)
#define LINK_TARGET L"LinkTargetProp"
typedef struct __PARTSIZE
{
HWND hwnd;
LONG cx;
LONG cy;
} PARTSIZE;
typedef struct __LINKSIZEINFO
{
PARTSIZE tos;
PARTSIZE and;
PARTSIZE privacy;
LONG spaceWidth;
RECT linkMargins;
} LINKSIZEINFO;
static HRESULT CALLBACK LoginPopupAgreement_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd) return E_INVALIDARG;
*instance = new LoginPopupAgreement(hwnd);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPopupAgreement::LoginPopupAgreement(HWND hwnd)
: LoginPopup(hwnd, -1, MAKEINTRESOURCE(IDS_POPUP_AGREEMENT_TITLE))
{
}
LoginPopupAgreement::~LoginPopupAgreement()
{
}
HWND LoginPopupAgreement::CreatePopup(HWND hParent, LoginProvider *provider)
{
if (NULL == provider)
return NULL;
return LoginPopup::CreatePopup(MAKEINTRESOURCE(IDD_POPUP_AGREEMENT), hParent, (LPARAM)provider, LoginPopupAgreement_CreateInstance);
}
void LoginPopupAgreement::UpdateLayout(BOOL fRedraw)
{
LoginPopup::UpdateLayout(fRedraw);
RECT rect;
if (FALSE == GetInfoRect(&rect)) return;
const INT szButtons[] = { IDOK, IDCANCEL, };
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szButtons) + 1 + 2*3);
if (NULL == hdwp) return;
hdwp = LayoutButtons(hdwp, szButtons, ARRAYSIZE(szButtons), fRedraw, NULL);
LONG top = rect.top;
SIZE partSize;
HWND hText = GetDlgItem(hwnd, IDC_TEXT);
if (NULL != hText && FALSE != GetTextSize(hText, rect.right - rect.left, &partSize))
{
hdwp = DeferWindowPos(hdwp, hText, NULL, rect.left, top, partSize.cx, partSize.cy, flags);
if (NULL == hdwp) return;
top += partSize.cy;
}
top += marginLinkFirst;
hdwp = LayoutProviderLinks(hdwp, IDC_AOL, NULL, rect.left + marginLinkLeft, top, flags, &partSize);
if (NULL == hdwp) return;
if (0 != partSize.cy)
top += partSize.cy + marginLinkNext;
hdwp = LayoutProviderLinks(hdwp, IDC_3DPARTY, NULL, rect.left + marginLinkLeft, top, flags, &partSize);
if (NULL == hdwp) return;
EndDeferWindowPos(hdwp);
if (FALSE != fRedraw)
{
HWND hControl = GetDlgItem(hwnd, IDC_TEXT);
if (NULL != hControl) InvalidateRect(hControl, NULL, FALSE);
}
}
void LoginPopupAgreement::EndDialog(INT_PTR code)
{
NLPNRESULT result;
result.exitCode = code;
SendNotification(NLPN_RESULT, (NMHDR*)&result);
LoginPopup::EndDialog(code);
}
void LoginPopupAgreement::UpdateMargins()
{
RECT rect;
SetRect(&rect, 8, 8, 0, 2);
MapDialogRect(hwnd, &rect);
marginLinkLeft = rect.left;
marginLinkFirst = rect.top;
marginLinkNext = rect.bottom;
LoginPopup::UpdateMargins();
}
static BOOL ProviderLinks_GetSizeInfo(HWND hwnd, INT groupId, LINKSIZEINFO *sizeInfo)
{
if(NULL == sizeInfo)
return FALSE;
HWND hControl;
SIZE partSize;
SetRectEmpty(&sizeInfo->linkMargins);
hControl = GetDlgItem(hwnd, groupId + LINK_TOS);
if (NULL == hControl ||
0 == (WS_VISIBLE & GetWindowStyle(hControl)) ||
FALSE == CommandLink_GetIdealSize(hControl, &partSize))
{
ZeroMemory(&sizeInfo->tos, sizeof(PARTSIZE));
}
else
{
sizeInfo->tos.hwnd = hControl;
sizeInfo->tos.cx = partSize.cx;
sizeInfo->tos.cy = partSize.cy;
CommandLink_GetMargins(hControl, &sizeInfo->linkMargins);
}
hControl = GetDlgItem(hwnd, groupId + LINK_PRIVACY);
if (NULL == hControl ||
0 == (WS_VISIBLE & GetWindowStyle(hControl)) ||
FALSE == CommandLink_GetIdealSize(hControl, &partSize))
{
ZeroMemory(&sizeInfo->privacy, sizeof(PARTSIZE));
}
else
{
sizeInfo->privacy.hwnd = hControl;
sizeInfo->privacy.cx = partSize.cx;
sizeInfo->privacy.cy = partSize.cy;
if (IsRectEmpty(&sizeInfo->linkMargins))
CommandLink_GetMargins(hControl, &sizeInfo->linkMargins);
}
if (NULL == sizeInfo->tos.hwnd && NULL == sizeInfo->privacy.hwnd)
return FALSE;
ZeroMemory(&sizeInfo->and, sizeof(PARTSIZE));
sizeInfo->spaceWidth = 0;
if (NULL != sizeInfo->tos.hwnd && NULL != sizeInfo->privacy.hwnd)
{
hControl = GetDlgItem(hwnd, groupId + STATIC_AND);
if (NULL != hControl)
{
WCHAR szBuffer[64] = {0};
INT cchLen = (INT)SendMessage(hControl, WM_GETTEXT, ARRAYSIZE(szBuffer), (LPARAM)szBuffer);
if (cchLen > 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 fontOrig = (HFONT)SelectObject(hdc, font);
if (FALSE != GetTextExtentPoint32W(hdc, szBuffer, cchLen, &partSize))
{
sizeInfo->and.hwnd = hControl;
sizeInfo->and.cx = partSize.cx;
sizeInfo->and.cy = partSize.cy;
}
if (FALSE != GetTextExtentPoint32W(hdc, L" ", 1, &partSize))
{
sizeInfo->spaceWidth = partSize.cx;
}
SelectObject(hdc, fontOrig);
ReleaseDC(hControl, hdc);
}
}
}
}
return TRUE;
}
HDWP LoginPopupAgreement::LayoutProviderLinks(HDWP hdwp, INT groupId, HWND hwndInsertAfter, INT x, INT y, UINT flags, SIZE *size)
{
if (NULL == hdwp)
{
if (NULL == size)
return NULL;
x = 0;
y = 0;
}
LONG ox = x, cy = 0;
LINKSIZEINFO sizeInfo;
if (FALSE == ProviderLinks_GetSizeInfo(hwnd, groupId, &sizeInfo))
return hdwp;
if (NULL != sizeInfo.tos.hwnd)
{
if (NULL != hdwp)
{
hdwp = DeferWindowPos(hdwp, sizeInfo.tos.hwnd, hwndInsertAfter, x, y, sizeInfo.tos.cx, sizeInfo.tos.cy, flags);
if (NULL == hdwp) return NULL;
}
x += sizeInfo.tos.cx;
if (cy < sizeInfo.tos.cy) cy = sizeInfo.tos.cy;
}
if (NULL != sizeInfo.and.hwnd)
{
LONG top = y + ((sizeInfo.tos.cy - (sizeInfo.linkMargins.bottom + sizeInfo.linkMargins.top)) - sizeInfo.and.cy)/2;
LONG space = (sizeInfo.spaceWidth - sizeInfo.linkMargins.right);
if (space < 1) space = 1;
x += space;
if (NULL != hdwp)
{
hdwp = DeferWindowPos(hdwp, sizeInfo.and.hwnd, hwndInsertAfter, x, top, sizeInfo.and.cx, sizeInfo.and.cy, flags);
if (NULL == hdwp) return NULL;
}
x += sizeInfo.and.cx;
if (cy < sizeInfo.and.cy) cy = sizeInfo.and.cy;
}
if (NULL != sizeInfo.privacy.hwnd)
{
if (NULL != sizeInfo.and.hwnd)
{
LONG space = (sizeInfo.spaceWidth - sizeInfo.linkMargins.left);
if (space < 1) space = 1;
x += space;
}
if (NULL != hdwp)
{
hdwp = DeferWindowPos(hdwp, sizeInfo.privacy.hwnd, hwndInsertAfter, x, y, sizeInfo.privacy.cx, sizeInfo.privacy.cy, flags);
if (NULL == hdwp) return NULL;
}
x += sizeInfo.privacy.cx;
if (cy < sizeInfo.privacy.cy) cy = sizeInfo.privacy.cy;
}
if (NULL != size)
{
size->cx = (x - ox);
size->cy = cy;
}
return (NULL == hdwp) ? (HDWP)(TRUE) : hdwp;
}
BOOL LoginPopupAgreement::CreateProviderLinks(LPCWSTR pszProvider, LPCWSTR pszTos, LPCWSTR pszPrivacy, INT groupId, HWND hwndInsertAfter)
{
WCHAR szTemplate[256] = {0}, szBuffer[256] = {0};
UINT linkStyle = WS_CHILD | WS_TABSTOP | WS_GROUP | WS_VISIBLE |
CLS_DEFAULTCOLORS | CLS_HOTTRACK /*| CLS_ALWAYSUNDERLINE*/;
HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
LPWSTR pszUrl;
HWND hControl;
INT createdCount = 0;
INT failedCount = 0;
if (NULL != pszTos && L'\0' != *pszTos)
{
WASABI_API_LNGSTRINGW_BUF(IDS_TOSLINK_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, pszProvider);
hControl = CommandLink_CreateWindow(0, szBuffer, linkStyle, 0, 0, 0, 0, hwnd, groupId + LINK_TOS);
if (NULL != hControl)
{
pszUrl = LoginBox_CopyString(pszTos);
if (NULL == pszUrl || FALSE == SetProp(hControl, LINK_TARGET, pszUrl))
{
LoginBox_FreeString(pszUrl);
DestroyWindow(hControl);
hControl = NULL;
}
}
if (NULL != hControl)
{
SendMessage(hControl, WM_SETFONT, (WPARAM)font, 0L);
SetWindowPos(hControl, hwndInsertAfter, 0, 0,0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
hwndInsertAfter = hControl;
createdCount++;
}
else failedCount++;
}
if (0 == failedCount && NULL != pszPrivacy && L'\0' != *pszPrivacy)
{
WASABI_API_LNGSTRINGW_BUF(IDS_PRIVACYLINK_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, pszProvider);
hControl = CommandLink_CreateWindow(0, szBuffer, linkStyle, 0, 0, 0, 0, hwnd, groupId + LINK_PRIVACY);
if (NULL != hControl)
{
pszUrl = LoginBox_CopyString(pszPrivacy);
if (NULL == pszUrl || FALSE == SetProp(hControl, LINK_TARGET, pszUrl))
{
LoginBox_FreeString(pszUrl);
DestroyWindow(hControl);
hControl = NULL;
}
}
if (NULL != hControl)
{
SendMessage(hControl, WM_SETFONT, (WPARAM)font, 0L);
SetWindowPos(hControl, hwndInsertAfter, 0, 0,0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
hwndInsertAfter = hControl;
createdCount++;
}
else failedCount++;
}
if (0 == failedCount && createdCount > 1)
{
WASABI_API_LNGSTRINGW_BUF(IDS_AND, szBuffer, ARRAYSIZE(szBuffer));
hControl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", szBuffer, WS_CHILD | WS_VISIBLE | SS_LEFT,
0, 0, 0, 0, hwnd, (HMENU)(INT_PTR)(groupId + STATIC_AND), NULL, 0L);
if (NULL != hControl)
{
SendMessage(hControl, WM_SETFONT, (WPARAM)font, 0L);
SetWindowPos(hControl, hwndInsertAfter, 0, 0,0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
hwndInsertAfter = hControl;
createdCount++;
}
else
failedCount++;
}
if (0 != failedCount)
{
hControl = GetDlgItem(hwnd, (groupId + LINK_TOS));
if (NULL != hControl) DestroyWindow(hControl);
hControl = GetDlgItem(hwnd, (groupId + LINK_PRIVACY));
if (NULL != hControl) DestroyWindow(hControl);
hControl = GetDlgItem(hwnd, (groupId + STATIC_AND));
if (NULL != hControl) DestroyWindow(hControl);
}
return (0 == failedCount);
}
BOOL LoginPopupAgreement::OnInitDialog(HWND hFocus, LPARAM param)
{
LoginProvider *provider = (LoginProvider*)param;
if (NULL != provider)
{
WCHAR szName[128] = {0}, szTos[4096] = {0}, szPrivacy[4096] = {0};
if (FAILED(provider->GetTosLink(szTos, ARRAYSIZE(szTos))))
szTos[0] = L'\0';
if (FAILED(provider->GetPrivacyLink(szPrivacy, ARRAYSIZE(szPrivacy))))
szPrivacy[0] = L'\0';
if((L'\0' != szTos[0] || L'\0' != szPrivacy[0]) &&
SUCCEEDED(provider->GetName(szName, ARRAYSIZE(szName))))
{
CreateProviderLinks(szName, szTos, szPrivacy, IDC_3DPARTY, NULL);
}
}
CreateProviderLinks(L"AOL", L"https://new.aol.com/freeaolweb/resources/jsp/mem_tos.jsp",
L"http://about.aol.com/aolnetwork/mem_policy", IDC_AOL, NULL);
LoginPopup::OnInitDialog(hFocus, param);
HWND hAgree = GetDlgItem(hwnd, IDOK);
if (NULL != hAgree && (WS_VISIBLE == ((WS_VISIBLE | WS_DISABLED) & GetWindowStyle(hAgree))))
{
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hAgree, TRUE);
return TRUE;
}
return FALSE;
}
void LoginPopupAgreement::OnDestroy()
{
INT szLinks[] = {IDC_AOL_TOS, IDC_AOL_PRIVACY, IDC_3DPARTY_TOS, IDC_3DPARTY_PRIVACY, };
for (INT i = 0; i < ARRAYSIZE(szLinks); i++)
{
HWND hLink = GetDlgItem(hwnd, szLinks[i]);
if (NULL != hLink) DestroyWindow(hLink);
}
}
BOOL LoginPopupAgreement::OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut)
{
if (NULL == clientRect || NULL == rectOut)
return FALSE;
SIZE maxSize;
SIZE partSize;
maxSize.cx = 0;
maxSize.cy = 0;
if (((HDWP)TRUE) == LayoutProviderLinks(NULL, IDC_AOL, NULL, 0, 0, 0, &partSize))
{
if (maxSize.cx < partSize.cx) maxSize.cx = partSize.cx;
maxSize.cy += (partSize.cy + marginLinkFirst);
}
if (((HDWP)TRUE) == LayoutProviderLinks(NULL, IDC_3DPARTY, NULL, 0, 0, 0, &partSize))
{
if (maxSize.cx < partSize.cx) maxSize.cx = partSize.cx;
maxSize.cy += (partSize.cy + ((0 == maxSize.cy) ? marginLinkFirst : marginLinkNext));
}
if (0 != maxSize.cx)
maxSize.cx += marginLinkLeft;
if (0 != maxSize.cy)
maxSize.cy += marginLinkFirst;
LONG maxWidth = clientRect->right - clientRect->left -
(clientMargins.right + clientMargins.left) -
(infoMargins.right + infoMargins.left);
if (maxSize.cx > maxWidth)
maxSize.cx = maxWidth;
if (FALSE != GetTextSize(GetDlgItem(hwnd, IDC_TEXT), maxWidth, &partSize))
{
if (maxSize.cx < partSize.cx) maxSize.cx = partSize.cx;
maxSize.cy += partSize.cy;
}
if (FALSE == CalculateWindowRect(maxSize.cx, maxSize.cy, NULL, 0, TRUE, rectOut))
return FALSE;
LONG ox = clientRect->left + ((clientRect->right - clientRect->left) - (rectOut->right - rectOut->left))/2;
LONG oy = clientRect->top + ((clientRect->bottom - clientRect->top) - (rectOut->bottom - rectOut->top))/2;
if (ox < clientRect->left) ox = clientRect->left;
if (oy < clientRect->top) oy = clientRect->top;
OffsetRect(rectOut, ox, oy);
return TRUE;
}
HBRUSH LoginPopupAgreement::OnGetStaticColor(HDC hdc, HWND hControl)
{
HBRUSH hb = LoginPopup::OnGetStaticColor(hdc, hControl);
INT controlId = (NULL != hControl) ? (INT)GetWindowLongPtr(hControl, GWLP_ID) : 0;
switch(controlId)
{
case IDC_AOL_AND:
case IDC_3DPARTY_AND:
{
HWND hLink = GetDlgItem(hwnd, (controlId - STATIC_AND));
if (NULL != hLink)
{
// SetTextColor(hdc, CommandLink_GetTextColor(hLink));
}
}
break;
}
return hb;
}
void LoginPopupAgreement::OnParentNotify(UINT eventId, UINT wParam, LPARAM lParam)
{
switch(eventId)
{
case WM_DESTROY:
switch(wParam)
{
case IDC_AOL_TOS:
case IDC_AOL_PRIVACY:
case IDC_3DPARTY_TOS:
case IDC_3DPARTY_PRIVACY:
{
LPWSTR url = (LPWSTR)GetProp((HWND)lParam, LINK_TARGET);
RemoveProp((HWND)lParam, LINK_TARGET);
LoginBox_FreeString(url);
}
break;
}
break;
}
LoginPopup::OnParentNotify(eventId, wParam, lParam);
}
void LoginPopupAgreement::OnLinkClicked(HWND hLink)
{
if (NULL == hLink)
return;
LPCWSTR pszTarget = (LPCWSTR)GetProp(hLink, LINK_TARGET);
if (NULL != pszTarget && L'\0' != *pszTarget)
{
LoginBox_OpenUrl(hwnd, pszTarget, TRUE);
}
}
LRESULT LoginPopupAgreement::OnNotify(UINT controlId, const NMHDR *pnmh)
{
switch(controlId)
{
case IDC_AOL_TOS:
case IDC_AOL_PRIVACY:
case IDC_3DPARTY_TOS:
case IDC_3DPARTY_PRIVACY:
switch(pnmh->code)
{
case NM_CLICK:
OnLinkClicked(pnmh->hwndFrom);
return 0;
}
break;
}
return LoginPopup::OnNotify(controlId, pnmh);
}

View File

@@ -0,0 +1,48 @@
#ifndef NULLSOFT_AUTH_LOGINPOPUP_AGREEMENT_HEADER
#define NULLSOFT_AUTH_LOGINPOPUP_AGREEMENT_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPopup.h"
class LoginProvider;
class LoginPopupAgreement : public LoginPopup
{
protected:
LoginPopupAgreement(HWND hwnd);
~LoginPopupAgreement();
public:
static HWND CreatePopup(HWND hParent, LoginProvider *provider);
protected:
void UpdateLayout(BOOL fRedraw);
void EndDialog(INT_PTR code);
void UpdateMargins();
BOOL CreateProviderLinks(LPCWSTR pszProvider, LPCWSTR pszTos, LPCWSTR pszPrivacy, INT groupId, HWND hwndInsertAfter);
HDWP LayoutProviderLinks(HDWP hdwp, INT groupId, HWND hwndInsertAfter, INT x, INT y, UINT flags, SIZE *size); // pass hdwp = NULL to get ideal size
void OnLinkClicked(HWND hLink);
HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
LRESULT OnNotify(UINT controlId, const NMHDR *pnmh);
void OnParentNotify(UINT eventId, UINT wParam, LPARAM lParam);
BOOL OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
void OnDestroy();
protected:
LONG marginLinkLeft;
LONG marginLinkFirst;
LONG marginLinkNext;
private:
friend static HRESULT CALLBACK LoginPopupAgreement_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance);
};
#endif //NULLSOFT_AUTH_LOGINPOPUP_AGREEMENT_HEADER

View File

@@ -0,0 +1,253 @@
#include "./popupMessage.h"
#include "./loginNotifier.h"
#include "./common.h"
#include "../resource.h"
#include "../api.h"
#include <windows.h>
#include <strsafe.h>
typedef struct __MESSAGECREATEPARAM
{
UINT type;
LPCWSTR title;
LPCWSTR message;
LoginPopupMessage::ResultCallback callback;
LPARAM param;
} MESSAGECREATEPARAM;
typedef struct __MESSAGEBUTTON
{
INT id;
LPCWSTR pTitle;
BOOL fGroup;
BOOL fDisabled;
BOOL fDefault;
} MESSAGEBUTTON;
const static MESSAGEBUTTON szTypeContinue[] =
{
{ IDOK, MAKEINTRESOURCE(IDS_BUTTON_CONTINUE), TRUE, FALSE, TRUE, },
};
const static MESSAGEBUTTON szTypeYesNo[] =
{
{ IDYES, MAKEINTRESOURCE(IDS_BUTTON_YES), TRUE, FALSE, TRUE, },
{ IDNO, MAKEINTRESOURCE(IDS_BUTTON_NO), FALSE, FALSE, FALSE, },
};
static HRESULT CALLBACK LoginPopupMessage_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd) return E_INVALIDARG;
*instance = new LoginPopupMessage(hwnd);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPopupMessage::LoginPopupMessage(HWND hwnd)
: LoginPopup(hwnd, NLNTYPE_INFORMATION, NULL), callback(NULL), param(0L),
buttonsCount(0)
{
memset(szButtons, 0, sizeof(szButtons));
}
LoginPopupMessage::~LoginPopupMessage()
{
}
HWND LoginPopupMessage::CreatePopup(HWND hParent, LPCWSTR pszTitle, LPCWSTR pszMessage, UINT uType, ResultCallback callback, LPARAM param)
{
switch(typeMask & uType)
{
case typeContinue:
case typeYesNo:
break;
default:
return NULL;
}
MESSAGECREATEPARAM createParam;
createParam.type = uType;
createParam.title = pszTitle;
createParam.message = pszMessage;
createParam.callback = callback;
createParam.param = param;
return LoginPopup::CreatePopup(MAKEINTRESOURCE(IDD_POPUP_MESSAGE), hParent,
(LPARAM)&createParam, LoginPopupMessage_CreateInstance);
}
void LoginPopupMessage::UpdateLayout(BOOL fRedraw)
{
LoginPopup::UpdateLayout(fRedraw);
RECT rect;
if (FALSE == GetInfoRect(&rect)) return;
HDWP hdwp = BeginDeferWindowPos(1 + buttonsCount);
if (NULL == hdwp) return;
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
if (FALSE == fRedraw) flags |= SWP_NOREDRAW;
HWND hMessage = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL != hMessage)
{
hdwp = DeferWindowPos(hdwp, hMessage, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags);
if (NULL == hdwp) return;
}
if (NULL != buttonsCount)
hdwp = LayoutButtons(hdwp, szButtons, buttonsCount, fRedraw, NULL);
EndDeferWindowPos(hdwp);
}
void LoginPopupMessage::EndDialog(INT_PTR code)
{
ResultCallback callbackCopy = callback;
LPARAM paramCopy = param;
NLPNRESULT result;
result.exitCode = code;
SendNotification(NLPN_RESULT, (NMHDR*)&result);
if (NULL != callbackCopy)
callbackCopy(hwnd, code, paramCopy);
LoginPopup::EndDialog(code);
}
static BOOL LoginPopupMessage_CreateButtons(HWND hwnd, const MESSAGEBUTTON *buttonList, UINT *buttonsCount, INT *buttonIdList)
{
if (NULL == hwnd || NULL == buttonList || NULL == buttonsCount || 0 == *buttonsCount)
return FALSE;
UINT count = *buttonsCount;
*buttonsCount = 0;
WCHAR szBuffer[256] = {0};
RECT rect;
SetRect(&rect, 50, 15, 0, 0);
MapDialogRect(hwnd, &rect);
LONG width = rect.left;
LONG height = rect.top;
HFONT font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
for (UINT i = 0; i < count; i++)
{
LPCWSTR title = buttonList[i].pTitle;
if (NULL != title && FALSE != IS_INTRESOURCE(title))
{
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)title, szBuffer, ARRAYSIZE(szBuffer));
title = szBuffer;
}
UINT style = BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP;
if (FALSE != buttonList[i].fGroup) style |= WS_GROUP;
if (FALSE != buttonList[i].fDisabled) style |= WS_DISABLED;
if (FALSE != buttonList[i].fDefault) style |= BS_DEFPUSHBUTTON;
HWND hButton = CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Button", title, style,
0, 0, width, height, hwnd, (HMENU)(INT_PTR)buttonList[i].id, NULL, 0L);
if (NULL != hButton)
{
if (NULL != font)
SendMessage(hButton, WM_SETFONT, (WPARAM)font, 0L);
if (NULL != buttonIdList)
buttonIdList[*buttonsCount] = buttonList[i].id;
(*buttonsCount)++;
}
}
return TRUE;
}
BOOL LoginPopupMessage::OnInitDialog(HWND hFocus, LPARAM param)
{
MESSAGECREATEPARAM *createParam = (MESSAGECREATEPARAM*)param;
if (NULL != createParam)
{
callback = createParam->callback;
param = createParam->param;
switch(iconMask & createParam->type)
{
case iconInfo: popupType = NLNTYPE_INFORMATION; break;
case iconWarning: popupType = NLNTYPE_WARNING; break;
case iconError: popupType = NLNTYPE_ERROR; break;
}
SetTitle(popupType, createParam->title);
switch(typeMask & createParam->type)
{
case typeContinue:
buttonsCount = ARRAYSIZE(szTypeContinue);
LoginPopupMessage_CreateButtons(hwnd, szTypeContinue, &buttonsCount, szButtons);
break;
case typeYesNo:
buttonsCount = ARRAYSIZE(szTypeYesNo);
LoginPopupMessage_CreateButtons(hwnd, szTypeYesNo, &buttonsCount, szButtons);
break;
}
HWND hMessage = GetDlgItem(hwnd, IDC_MESSAGE);
if (NULL != hMessage)
{
if (NULL != createParam->message && FALSE != IS_INTRESOURCE(createParam->message))
{
WCHAR szBuffer[4096] = {0};
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)createParam->message, szBuffer, ARRAYSIZE(szBuffer));
SendMessage(hMessage, WM_SETTEXT, 0, (LPARAM)szBuffer);
}
else
SendMessage(hMessage, WM_SETTEXT, 0, (LPARAM)createParam->message);
}
}
return LoginPopup::OnInitDialog(hFocus, param);
}
BOOL LoginPopupMessage::OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut)
{
if (NULL == clientRect || NULL == rectOut)
return FALSE;
SIZE size;
LONG maxWidth = clientRect->right - clientRect->left -
(clientMargins.right + clientMargins.left) -
(infoMargins.right + infoMargins.left);
if (FALSE == GetTextSize(GetDlgItem(hwnd, IDC_MESSAGE), maxWidth, &size))
{
size.cx = 0;
size.cy = 0;
}
if (FALSE == CalculateWindowRect(size.cx, size.cy, szButtons, buttonsCount, TRUE, rectOut))
return FALSE;
LONG ox = clientRect->left + ((clientRect->right - clientRect->left) - (rectOut->right - rectOut->left))/2;
LONG oy = clientRect->top + ((clientRect->bottom - clientRect->top) - (rectOut->bottom - rectOut->top))/2;
if (ox < clientRect->left) ox = clientRect->left;
if (oy < clientRect->top) oy = clientRect->top;
OffsetRect(rectOut, ox, oy);
return TRUE;
}

View File

@@ -0,0 +1,52 @@
#ifndef NULLSOFT_AUTH_LOGINPOPUP_MESSAGE_HEADER
#define NULLSOFT_AUTH_LOGINPOPUP_MESSAGE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPopup.h"
class LoginPopupMessage : public LoginPopup
{
public:
typedef enum
{
typeMask = 0x0000FFFF,
typeContinue = 0x00000000,
typeYesNo = 0x00000001,
iconMask = 0xFFFF0000,
iconInfo = 0x00000000,
iconWarning = 0x00010000,
iconError = 0x00020000,
} Type;
typedef void (CALLBACK *ResultCallback)(HWND /*hPopup*/, INT_PTR /*resultCode*/, LPARAM param);
protected:
LoginPopupMessage(HWND hwnd);
~LoginPopupMessage();
public:
static HWND CreatePopup(HWND hParent, LPCWSTR pszTitle, LPCWSTR pszMessage, UINT uType, ResultCallback callback, LPARAM param);
protected:
void UpdateLayout(BOOL fRedraw);
void EndDialog(INT_PTR code);
BOOL OnInitDialog(HWND hFocus, LPARAM param);
BOOL OnUpdateWindowPos(const RECT* clientRect, RECT *rectOut);
protected:
ResultCallback callback;
LPARAM param;
INT szButtons[8];
UINT buttonsCount;
private:
friend static HRESULT CALLBACK LoginPopupMessage_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance);
};
#endif //NULLSOFT_AUTH_LOGINPOPUP_MESSAGE_HEADER

View File

@@ -0,0 +1,405 @@
#include "./popupPasscode.h"
#include "./common.h"
#include "./loginNotifier.h"
#include "./dataCredentials.h"
#include "./editboxExtender.h"
#include "../resource.h"
#include "../api.h"
#include "../api_auth.h"
#include <windows.h>
#include <commctrl.h>
#include <strsafe.h>
#define MAX_PASSCODE_LENGTH 6
#define MIN_PASSCODE_LENGTH 6
#define TIMER_UPDATETITLE_ID 14
#define TIMER_UPDATETITLE_DELAY 50
static HRESULT CALLBACK LoginPopupPasscode_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == hwnd) return E_INVALIDARG;
*instance = new LoginPopupPasscode(hwnd);
if (NULL == instance) return E_OUTOFMEMORY;
return S_OK;
}
LoginPopupPasscode::LoginPopupPasscode(HWND hwnd)
: LoginPopup(hwnd, -1, MAKEINTRESOURCE(IDS_POPUP_PASSCODE_TITLE)),
loginData(NULL), message(NULL), messageType(-1)
{
}
LoginPopupPasscode::~LoginPopupPasscode()
{
if (NULL != loginData)
loginData->Release();
LoginBox_FreeString(message);
}
HWND LoginPopupPasscode::CreatePopup(HWND hParent, LoginData *loginData)
{
LoginDataCredentials *credentials;
if (NULL == loginData ||
FAILED(loginData->QueryInterface(IID_LoginDataCredentials, (void**)&credentials)))
{
return NULL;
}
HWND hwnd = LoginPopup::CreatePopup(MAKEINTRESOURCE(IDD_POPUP_PASSCODE), hParent, (LPARAM)credentials, LoginPopupPasscode_CreateInstance);
credentials->Release();
return hwnd;
}
void LoginPopupPasscode::UpdateLayout(BOOL fRedraw)
{
LoginPopup::UpdateLayout(fRedraw);
RECT rect;
if (FALSE == GetInfoRect(&rect)) return;
const INT szButtons[] = { IDOK, };
const INT szControls[] = { IDC_PASSCODE_TITLE, IDC_PASSCODE_EDIT, IDC_PASSCODE_HINT, };
HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(szControls) + ARRAYSIZE(szButtons));
if (NULL == hdwp) return;
hdwp = LayoutButtons(hdwp, szButtons, ARRAYSIZE(szButtons), fRedraw, NULL);
LONG top = rect.top;
RECT controlRect;
for(INT i = 0; i < ARRAYSIZE(szControls); i++)
{
HWND hControl = GetDlgItem(hwnd, szControls[i]);
if (NULL == hControl || FALSE == GetWindowRect(hControl, &controlRect))
continue;
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&controlRect, 2);
hdwp = DeferWindowPos(hdwp, hControl, NULL,
rect.left, top, rect.right - rect.left, controlRect.bottom - controlRect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
if (NULL == hdwp)
return;
top += controlRect.bottom - controlRect.top;
switch(szControls[i])
{
case IDC_PASSCODE_TITLE: top += 2; break;
}
}
EndDeferWindowPos(hdwp);
}
void LoginPopupPasscode::EndDialog(INT_PTR code)
{
if (IDOK == code)
{
code = -1;
if (NULL != loginData)
{
HWND hEdit = GetDlgItem(hwnd, IDC_PASSCODE_EDIT);
if (NULL != hEdit)
{
WCHAR szBuffer[64] = {0};
GetWindowText(hEdit, szBuffer, ARRAYSIZE(szBuffer));
if(SUCCEEDED(loginData->SetPasscode(szBuffer)))
code = IDOK;
}
}
}
NPPNRESULT result;
result.exitCode = code;
result.loginData = loginData;
if (NULL != result.loginData)
result.loginData->AddRef();
SendNotification(NPPN_RESULT, (NMHDR*)&result);
if (NULL != result.loginData)
result.loginData->Release();
LoginPopup::EndDialog(code);
}
BOOL LoginPopupPasscode::Validate()
{
BOOL validatedOk = TRUE;
HWND hEdit = GetDlgItem(hwnd, IDC_PASSCODE_EDIT);
if (NULL == hEdit)
{
SetAlert(NLNTYPE_ERROR, MAKEINTRESOURCE(IDS_ERR_UNEXPECTED));
validatedOk = FALSE;
}
else
{
INT cchText = (INT)SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0L);
if (cchText < MIN_PASSCODE_LENGTH || cchText > MAX_PASSCODE_LENGTH)
{
WCHAR szBuffer[256] = {0}, szTemplate[256] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_ERR_PASSCODE_BADLENGTH_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, MAX_PASSCODE_LENGTH);
SetAlert(NLNTYPE_ERROR, szBuffer);
validatedOk = FALSE;
}
else
{
WCHAR szPasscode[MAX_PASSCODE_LENGTH + 1] = {0};
WORD szType[MAX_PASSCODE_LENGTH] = {0};
SendMessage(hEdit, WM_GETTEXT, (WPARAM)ARRAYSIZE(szPasscode), (LPARAM)szPasscode);
if (FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, szPasscode, cchText, szType))
{
for(INT i = 0; i < cchText; i++)
{
if (0 == (C1_DIGIT & szType[i]))
{
SetAlert(NLNTYPE_ERROR, MAKEINTRESOURCE(IDS_ERR_PASSCODE_ONLYDIGITS));
validatedOk = FALSE;
break;
}
}
}
else
{
SetAlert(NLNTYPE_ERROR, MAKEINTRESOURCE(IDS_ERR_UNEXPECTED));
validatedOk = FALSE;
}
}
}
UpdateTitle(TRUE);
return validatedOk;
}
BOOL LoginPopupPasscode::OnInitDialog(HWND hFocus, LPARAM param)
{
loginData = (LoginDataCredentials*)param;
if (NULL != loginData)
loginData->AddRef();
if (NULL != loginData)
{
LPCWSTR pcode = loginData->GetPasscode();
if (NULL != pcode && L'\0' != *pcode)
{
SetAlert(NLNTYPE_ERROR, MAKEINTRESOURCE(IDS_ERR_PASSCODE_INVALID));
UpdateTitle(FALSE);
}
}
HWND hEdit = GetDlgItem(hwnd, IDC_PASSCODE_EDIT);
if (NULL != hEdit)
{
EditboxExtender_AttachWindow(hEdit);
}
HWND hHint = GetDlgItem(hwnd, IDC_PASSCODE_HINT);
if (NULL != hHint)
{
WCHAR szBuffer[128], szTemplate[128] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_PASSCODE_EDIT_HINT, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, MAX_PASSCODE_LENGTH);
SendMessage(hHint, WM_SETTEXT, 0, (LPARAM)szBuffer);
}
return LoginPopup::OnInitDialog(hFocus, param);
}
void LoginPopupPasscode::OnCommand(UINT commandId, UINT eventType, HWND hControl)
{
if (IDOK == commandId && FALSE == Validate())
return;
LoginPopup::OnCommand(commandId, eventType, hControl);
}
LRESULT LoginPopupPasscode::OnNotify(UINT controlId, const NMHDR *pnmh)
{
switch(controlId)
{
case IDC_PASSCODE_EDIT:
switch(pnmh->code)
{
case NM_CHAR:
return OnEditboxChar(pnmh->hwndFrom, ((NMCHAR*)pnmh)->ch);
case NM_KEYDOWN:
return OnEditboxKey(pnmh->hwndFrom, ((NMKEY*)pnmh)->nVKey, ((NMKEY*)pnmh)->uFlags);
case EENM_PASTE:
return OnEditboxPaste(pnmh->hwndFrom, ((EENMPASTE*)pnmh)->text);
}
return 0;
}
return LoginPopup::OnNotify(controlId, pnmh);
}
HBRUSH LoginPopupPasscode::OnGetStaticColor(HDC hdc, HWND hControl)
{
HBRUSH hb = LoginPopup::OnGetStaticColor(hdc, hControl);
INT controlId = (NULL != hControl) ? (INT)GetWindowLongPtr(hControl, GWLP_ID) : 0;
switch(controlId)
{
case IDC_PASSCODE_HINT:
SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
break;
}
return hb;
}
LRESULT LoginPopupPasscode::OnEditboxKey(HWND hEdit, UINT vKey, UINT flags)
{
if (-1 != alertType)
{
RemoveAlert();
SetTimer(hwnd, TIMER_UPDATETITLE_ID, TIMER_UPDATETITLE_DELAY, NULL);
}
return 0L;
}
LRESULT LoginPopupPasscode::OnEditboxChar(HWND hEdit, UINT ch)
{
if (VK_BACK == ch)
return FALSE;
BOOL filtered = FALSE;
INT selBegin, selEnd;
SendMessage(hEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
INT cchText = (INT)SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0L);
if (selBegin == selEnd && cchText >= MAX_PASSCODE_LENGTH)
{
WCHAR szBuffer[256] = {0}, szTemplate[256] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_ERR_PASSCODE_BADLENGTH_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, MAX_PASSCODE_LENGTH);
SetAlert(NLNTYPE_WARNING, szBuffer);
KillTimer(hwnd, TIMER_UPDATETITLE_ID);
UpdateTitle(TRUE);
filtered = TRUE;
}
else
{
WORD charType;
if (FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, (WCHAR*)&ch, 1, &charType))
{
if (0 == (C1_DIGIT & charType))
{
SetAlert(NLNTYPE_WARNING, MAKEINTRESOURCE(IDS_ERR_PASSCODE_ONLYDIGITS));
KillTimer(hwnd, TIMER_UPDATETITLE_ID);
UpdateTitle(TRUE);
filtered = TRUE;
}
}
}
return filtered;
}
LRESULT LoginPopupPasscode::OnEditboxPaste(HWND hEdit, LPCWSTR pszText)
{
if (NULL == pszText)
return TRUE;
INT cchText = lstrlen(pszText);
if (0 == cchText) return TRUE;
WCHAR szBuffer[MAX_PASSCODE_LENGTH + 1] = {0};
INT iBuffer = 0;
WORD charType;
BOOL validatedOk = TRUE;
INT maxSize = MAX_PASSCODE_LENGTH - (INT)SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0L);
if (maxSize < MAX_PASSCODE_LENGTH)
{
INT selBegin, selEnd;
SendMessage(hEdit, EM_GETSEL, (WPARAM)&selBegin, (LPARAM)&selEnd);
selEnd -= selBegin;
if (selEnd < 0) selEnd = -selBegin;
maxSize += selEnd;
}
for (INT i =0; i <cchText; i++)
{
if (FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &pszText[i], 1, &charType))
{
SetAlert(NLNTYPE_WARNING, MAKEINTRESOURCE(IDS_ERR_UNEXPECTED));
validatedOk = FALSE;
break;
}
else if (0 == (C1_DIGIT & charType))
{
if (0 == ((C1_SPACE | C1_CNTRL | C1_BLANK) & charType))
{
SetAlert(NLNTYPE_WARNING, MAKEINTRESOURCE(IDS_ERR_PASSCODE_ONLYDIGITS));
validatedOk = FALSE;
break;
}
}
else
{
if (iBuffer > maxSize)
{
WCHAR szBuffer[256], szTemplate[256] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_ERR_PASSCODE_BADLENGTH_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), szTemplate, MAX_PASSCODE_LENGTH);
SetAlert(NLNTYPE_WARNING, szBuffer);
validatedOk = FALSE;
break;
}
else
{
szBuffer[iBuffer] = pszText[i];
iBuffer++;
}
}
}
if(FALSE != validatedOk)
{
szBuffer[iBuffer] = L'\0';
SendMessage(hEdit, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)szBuffer);
}
else
{
UpdateTitle(TRUE);
}
return TRUE;
}
INT_PTR LoginPopupPasscode::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_TIMER:
switch(wParam)
{
case TIMER_UPDATETITLE_ID:
KillTimer(hwnd, wParam);
UpdateTitle((-1 != alertType));
return TRUE;
}
break;
}
return LoginPopup::DialogProc(uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,65 @@
#ifndef NULLSOFT_AUTH_LOGINPOPUP_PASSCODE_HEADER
#define NULLSOFT_AUTH_LOGINPOPUP_PASSCODE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginPopup.h"
class LoginData;
class LoginDataCredentials;
// notifications
#define NPPN_FIRST (120)
typedef struct __NPPNRESULT
{
NMHDR hdr;
INT_PTR exitCode;
LoginData *loginData;
} NPPNRESULT;
#define NPPN_RESULT (NPPN_FIRST + 0)
class LoginPopupPasscode : public LoginPopup
{
protected:
LoginPopupPasscode(HWND hwnd);
~LoginPopupPasscode();
public:
static HWND CreatePopup(HWND hParent, LoginData *loginData);
protected:
void UpdateLayout(BOOL fRedraw);
void EndDialog(INT_PTR code);
BOOL Validate();
BOOL OnInitDialog(HWND hFocus, LPARAM param);
void OnCommand(UINT commandId, UINT eventType, HWND hControl);
LRESULT OnNotify(UINT controlId, const NMHDR *pnmh);
HBRUSH OnGetStaticColor(HDC hdc, HWND hControl);
LRESULT OnEditboxChar(HWND hEdit, UINT ch);
LRESULT OnEditboxKey(HWND hEdit, UINT vKey, UINT flags);
LRESULT OnEditboxPaste(HWND hEdit, LPCWSTR pszText);
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
LoginDataCredentials *loginData;
LPWSTR message;
UINT messageType;
private:
friend static HRESULT CALLBACK LoginPopupPasscode_CreateInstance(HWND hwnd, LPARAM param, LoginPopup **instance);
};
#endif //NULLSOFT_AUTH_LOGINPOPUP_PASSCODE_HEADER

View File

@@ -0,0 +1,112 @@
#include "./common.h"
#include "./providerEnumerator.h"
#include "./loginProvider.h"
LoginProviderEnumerator::LoginProviderEnumerator()
: ref(1), cursor(0), list(NULL), size(0)
{
}
LoginProviderEnumerator::~LoginProviderEnumerator()
{
if (NULL != list)
{
size_t index = size;
while(index--)
{
LoginProvider *provider = list[index];
if (NULL != provider) provider->Release();
}
free(list);
}
}
ULONG LoginProviderEnumerator::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginProviderEnumerator::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
HRESULT LoginProviderEnumerator::CreateInstance(LoginProvider **list, size_t size, LoginProviderEnumerator **instance)
{
if (NULL == instance) return E_POINTER;
if (NULL == list) return E_INVALIDARG;
LoginProviderEnumerator *enumerator = new LoginProviderEnumerator();
if(NULL == enumerator)
return E_OUTOFMEMORY;
if (0 != size)
{
enumerator->list = (LoginProvider**)calloc(size, sizeof(LoginProvider*));
if (NULL == enumerator->list)
{
enumerator->Release();
return E_OUTOFMEMORY;
}
enumerator->size = size;
CopyMemory(enumerator->list, list, size * sizeof(LoginProvider*));
}
*instance = enumerator;
return S_OK;
}
HRESULT LoginProviderEnumerator::Next(ULONG listSize, LoginProvider **elementList, ULONG *elementCount)
{
if (NULL == elementList || 0 == listSize) return E_INVALIDARG;
if (cursor >= size)
{
if (NULL != elementCount) *elementCount = 0;
return S_FALSE;
}
ULONG count = 0;
for (;cursor < size && count < listSize; cursor++)
{
LoginProvider *provider = list[cursor];
if (NULL != provider)
{
provider->AddRef();
elementList[count] = provider;
count++;
}
}
if (NULL != elementCount) *elementCount = count;
return (count == listSize) ? S_OK : S_FALSE;
}
HRESULT LoginProviderEnumerator::Reset(void)
{
cursor = 0;
return S_OK;
}
HRESULT LoginProviderEnumerator::Skip(ULONG elementCount)
{
cursor += elementCount;
if (cursor >= size)
{
cursor = (size - 1);
return S_FALSE;
}
return S_OK;
}

View File

@@ -0,0 +1,38 @@
#ifndef NULLSOFT_AUTH_LOGIN_PROVIDER_ENUMERATOR_HEADER
#define NULLSOFT_AUTH_LOGIN_PROVIDER_ENUMERATOR_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginProvider;
class LoginProviderEnumerator
{
protected:
LoginProviderEnumerator();
~LoginProviderEnumerator();
public:
static HRESULT CreateInstance(LoginProvider **list, size_t size, LoginProviderEnumerator **instance);
public:
ULONG AddRef();
ULONG Release();
HRESULT Next(ULONG listSize, LoginProvider **elementList, ULONG *elementCount);
HRESULT Reset(void);
HRESULT Skip(ULONG elementCount);
protected:
ULONG ref;
size_t cursor;
size_t size;
LoginProvider **list;
};
#endif //NULLSOFT_AUTH_LOGIN_PROVIDER_ENUMERATOR_HEADER

View File

@@ -0,0 +1,142 @@
#include "./providerLoader.h"
#include "./providerEnumerator.h"
#include "./xmlInt32Parser.h"
#include "../api.h"
#include "../../xml/obj_xml.h"
#include <api/service/waservicefactory.h>
LoginProviderLoader::LoginProviderLoader()
{
}
LoginProviderLoader::~LoginProviderLoader()
{
}
HRESULT LoginProviderLoader::ReadXml(LPCWSTR pszPath, LoginProviderEnumerator **enumerator, INT *prefVisible)
{
if (NULL == enumerator) return E_POINTER;
*enumerator = NULL;
if (NULL == pszPath || L'\0' == *pszPath)
return E_INVALIDARG;
HANDLE hFile = CreateFile(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
DWORD error = GetLastError();
return HRESULT_FROM_WIN32(error);
}
HRESULT hr;
if (NULL != WASABI_API_SVC)
{
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
obj_xml *reader = (NULL != sf) ? (obj_xml*)sf->getInterface() : NULL;
if (NULL != reader)
{
if (OBJ_XML_SUCCESS == reader->xmlreader_open())
{
providerList.clear();
parser.SetReader(reader);
XmlInt32Parser visibleParser;
reader->xmlreader_registerCallback(L"loginProviders\fprovider", this);
if (NULL != prefVisible)
reader->xmlreader_registerCallback(L"loginProviders\fvisibleProviders", &visibleParser);
hr = FeedFile(reader, hFile, 8192);
reader->xmlreader_close();
parser.SetReader(NULL);
if (SUCCEEDED(hr))
hr = LoginProviderEnumerator::CreateInstance(providerList.begin(), providerList.size(), enumerator);
if (NULL != prefVisible && FAILED(visibleParser.GetValue(prefVisible)))
*prefVisible = 0;
}
else
hr = E_FAIL;
sf->releaseInterface(reader);
}
else
hr = E_FAIL;
}
else
hr = E_UNEXPECTED;
CloseHandle(hFile);
return hr;
}
HRESULT LoginProviderLoader::FeedFile(obj_xml *reader, HANDLE hFile, DWORD bufferSize)
{
if (NULL == reader || INVALID_HANDLE_VALUE == hFile || 0 == bufferSize)
return E_INVALIDARG;
BYTE *buffer = (BYTE*)calloc(bufferSize, sizeof(BYTE));
if (NULL == buffer) return E_OUTOFMEMORY;
HRESULT hr;
INT readerCode = OBJ_XML_SUCCESS;
for(;;)
{
DWORD read = 0;
if (FALSE == ReadFile(hFile, buffer, bufferSize, &read, NULL) || 0 == read)
{
DWORD errorCode = GetLastError();
hr = HRESULT_FROM_WIN32(errorCode);
if (0 == read && OBJ_XML_SUCCESS == readerCode)
reader->xmlreader_feed(0, 0);
break;
}
readerCode = reader->xmlreader_feed(buffer, read);
if (OBJ_XML_SUCCESS != readerCode)
{
hr = E_FAIL;
break;
}
}
free(buffer);
return hr;
}
void LoginProviderLoader::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
parser.Begin(params);
}
void LoginProviderLoader::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
LoginProvider *provider;
if (SUCCEEDED(parser.End(&provider)))
{
providerList.push_back(provider);
}
}
void LoginProviderLoader::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
parser.End(NULL);
}
#define CBCLASS LoginProviderLoader
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,44 @@
#ifndef NULLSOFT_AUTH_LOGIN_PROVIDER_LOADER_HEADER
#define NULLSOFT_AUTH_LOGIN_PROVIDER_LOADER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "../../nu/ptrlist.h"
#include "./providerParser.h"
class obj_xml;
class LoginProviderEnumerator;
class LoginProviderLoader : public ifc_xmlreadercallback
{
public:
LoginProviderLoader();
~LoginProviderLoader();
public:
HRESULT ReadXml(LPCWSTR pszPath, LoginProviderEnumerator **enumerator, INT *prefVisible);
private:
HRESULT FeedFile(obj_xml *reader, HANDLE hFile, DWORD bufferSize);
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
private:
typedef nu::PtrList<LoginProvider> ProviderList;
private:
ProviderList providerList;
LoginProviderParser parser;
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGIN_PROVIDER_LOADER_HEADER

View File

@@ -0,0 +1,136 @@
#include "./providerOperation.h"
#include "./loginProvider.h"
#include "./providerEnumerator.h"
LoginProviderOperation::LoginProviderOperation(LoginProvider *pSource, LoginProvider *pTarget, UINT uCode)
: ref(1), source(pSource), target(pTarget), code(uCode)
{
if (NULL != source) source->AddRef();
if (NULL != target) target->AddRef();
}
LoginProviderOperation::~LoginProviderOperation()
{
if (NULL != source) source->Release();
if (NULL != target) target->Release();
}
HRESULT LoginProviderOperation::CreateDeleteOperation(LoginProvider *pRemove, LoginProviderOperation **instance)
{
if (NULL == instance)
return E_POINTER;
if (NULL == pRemove)
{
*instance = NULL;
return E_INVALIDARG;
}
*instance = new LoginProviderOperation(pRemove, NULL, operationDelete);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT LoginProviderOperation::CreateReplaceOperation(LoginProvider *pSource, LoginProvider *pTarget, LoginProviderOperation **instance)
{
if (NULL == instance)
return E_POINTER;
if (NULL == pSource || NULL == pTarget)
{
*instance = NULL;
return E_INVALIDARG;
}
*instance = new LoginProviderOperation(pSource, pTarget, operationReplace);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
HRESULT LoginProviderOperation::CreateFromUpdate(LoginProvider *active, LoginProviderEnumerator *enumerator, LoginProviderOperation **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = NULL;
if (NULL == active || NULL == enumerator)
return E_INVALIDARG;
GUID testId, activeId(GUID_NULL);
HRESULT hr = active->GetId(&activeId);
if (FAILED(hr)) return hr;
LoginProvider *test;
BOOL providerFound = FALSE;
enumerator->Reset();
BOOL loop = TRUE;
while(TRUE == loop && S_OK == enumerator->Next(1, &test, NULL))
{
if (FAILED(test->GetId(&testId)))
{
hr = E_FAIL;
loop = FALSE;
}
else if(FALSE != IsEqualGUID(activeId, testId))
{
providerFound = TRUE;
if (S_OK == test->IsIdentical(active))
hr = S_FALSE;
else
hr = CreateReplaceOperation(active, test, instance);
loop = FALSE;
}
test->Release();
}
if (SUCCEEDED(hr) && FALSE == providerFound)
hr = CreateDeleteOperation(active, instance);
return hr;
}
ULONG LoginProviderOperation::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG LoginProviderOperation::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
UINT LoginProviderOperation::GetCode()
{
return code;
}
HRESULT LoginProviderOperation::GetSource(LoginProvider **provider)
{
if (NULL == provider) return E_POINTER;
*provider = source;
if (NULL != source)
source->AddRef();
return S_OK;
}
HRESULT LoginProviderOperation::GetTarget(LoginProvider **provider)
{
if (NULL == provider) return E_POINTER;
*provider = target;
if (NULL != target)
target->AddRef();
return S_OK;
}

View File

@@ -0,0 +1,47 @@
#ifndef NULLSOFT_AUTH_LOGIN_PROVIDER_OPERATION_HEADER
#define NULLSOFT_AUTH_LOGIN_PROVIDER_OPERATION_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class LoginProvider;
class LoginProviderEnumerator;
class LoginProviderOperation
{
public:
typedef enum
{
operationDelete = 0,
operationReplace = 1,
} OperationCode;
protected:
LoginProviderOperation(LoginProvider *pSource, LoginProvider *pTarget, UINT uCode);
~LoginProviderOperation();
public:
static HRESULT CreateDeleteOperation(LoginProvider *pRemove, LoginProviderOperation **instance);
static HRESULT CreateReplaceOperation(LoginProvider *pSource, LoginProvider *pTarget, LoginProviderOperation **instance);
static HRESULT CreateFromUpdate(LoginProvider *active, LoginProviderEnumerator *enumerator, LoginProviderOperation **instance);
public:
ULONG AddRef();
ULONG Release();
UINT GetCode();
HRESULT GetSource(LoginProvider **provider);
HRESULT GetTarget(LoginProvider **provider);
protected:
ULONG ref;
LoginProvider *source;
LoginProvider *target;
UINT code;
};
#endif //NULLSOFT_AUTH_LOGIN_PROVIDER_OPERATION_HEADER

View File

@@ -0,0 +1,194 @@
#include "./providerParser.h"
#include "./loginProvider.h"
#include "./loginTemplate.h"
#include "./loginCommand.h"
#include "./common.h"
//#include "../api.h"
#include "../../xml/obj_xml.h"
typedef void (CALLBACK *PROVIDERTAGCALLBACK)(LoginProvider* /*provider*/, LPCWSTR /*value*/);
typedef struct __PROVIDERTAG
{
LPCWSTR name;
PROVIDERTAGCALLBACK callback;
} PROVIDERTAG;
static void CALLBACK ProviderTag_Name(LoginProvider *provider, LPCWSTR value)
{
provider->SetName(value);
}
static void CALLBACK ProviderTag_ImagePath(LoginProvider *provider, LPCWSTR value)
{
provider->SetImagePath(value);
}
static void CALLBACK ProviderTag_Description(LoginProvider *provider, LPCWSTR value)
{
provider->SetDescription(value);
}
static void CALLBACK ProviderTag_TosLink(LoginProvider *provider, LPCWSTR value)
{
provider->SetTosLink(value);
}
static void CALLBACK ProviderTag_PrivacyLink(LoginProvider *provider, LPCWSTR value)
{
provider->SetPrivacyLink(value);
}
static void CALLBACK ProviderTag_HelpLink(LoginProvider *provider, LPCWSTR value)
{
provider->SetHelpLink(value);
}
static const PROVIDERTAG szProviderTags[PROVIDER_TAG_MAX] =
{
{L"name", ProviderTag_Name},
{L"icon", ProviderTag_ImagePath},
{L"description", ProviderTag_Description},
{L"tos", ProviderTag_TosLink},
{L"privacy", ProviderTag_PrivacyLink},
{L"help", ProviderTag_HelpLink},
};
LoginProviderParser::LoginProviderParser()
: reader(NULL), provider(NULL)
{
ZeroMemory(hitList, sizeof(hitList));
}
LoginProviderParser::~LoginProviderParser()
{
if (NULL != reader)
reader->Release();
if (NULL != provider)
provider->Release();
}
HRESULT LoginProviderParser::SetReader(obj_xml *pReader)
{
if (NULL != reader)
{
reader->Release();
}
reader = pReader;
if (NULL != reader)
reader->AddRef();
return S_OK;
}
HRESULT LoginProviderParser::Begin(ifc_xmlreaderparams *params)
{
if (NULL != provider)
return E_PENDING;
if (NULL == reader) return E_UNEXPECTED;
if (NULL == params) return E_INVALIDARG;
GUID providerId;
LPCWSTR pszId = params->getItemValue(L"id");
if (NULL != pszId && RPC_S_OK == UuidFromString((RPC_WSTR)pszId, &providerId))
{
if (FAILED(LoginProvider::CreateInstance(&providerId, &provider)))
provider = NULL;
}
if (NULL == provider)
return E_FAIL;
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fname", this);
reader->xmlreader_registerCallback(L"loginProviders\fprovider\ficon", this);
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fdescription", this);
reader->xmlreader_registerCallback(L"loginProviders\fprovider\ftos", this);
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fprivacy", this);
reader->xmlreader_registerCallback(L"loginProviders\fprovider\fhelp", this);
ZeroMemory(hitList, sizeof(hitList));
templateNodeParser.Begin(reader, provider);
commandNodeParser.Begin(reader, provider);
return S_OK;
}
HRESULT LoginProviderParser::End(LoginProvider **ppProvider)
{
templateNodeParser.End();
commandNodeParser.End();
reader->xmlreader_unregisterCallback(this);
if (NULL == provider || S_OK != provider->IsValid())
{
if (NULL != provider)
{
provider->Release();
provider = NULL;
}
if (NULL != ppProvider)
*ppProvider = NULL;
return E_FAIL;
}
if (NULL != ppProvider)
{
*ppProvider = provider;
if (NULL != provider)
provider->AddRef();
}
provider->Release();
provider = NULL;
return S_OK;
}
void LoginProviderParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
elementString.Clear();
}
void LoginProviderParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
for (INT i = 0; i < PROVIDER_TAG_MAX; i++)
{
if (FALSE == hitList[i] &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, szProviderTags[i].name, -1, xmltag, -1))
{
szProviderTags[i].callback(provider, elementString.Get());
hitList[i] = TRUE;
break;
}
}
}
void LoginProviderParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
elementString.Append(value);
}
void LoginProviderParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
{
elementString.Clear();
}
#define CBCLASS LoginProviderParser
START_DISPATCH;
VCB(ONSTARTELEMENT, Event_XmlStartElement)
VCB(ONENDELEMENT, Event_XmlEndElement)
VCB(ONCHARDATA, Event_XmlCharData)
VCB(ONERROR, Event_XmlError)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,48 @@
#ifndef NULLSOFT_AUTH_LOGIN_PROVIDER_PARSER_HEADER
#define NULLSOFT_AUTH_LOGIN_PROVIDER_PARSER_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../../xml/ifc_xmlreadercallback.h"
#include "./stringBuilder.h"
#include "./templateNodeParser.h"
#include "./commandNodeParser.h"
class obj_xml;
class LoginProvider;
#define PROVIDER_TAG_MAX 6
class LoginProviderParser : public ifc_xmlreadercallback
{
public:
LoginProviderParser();
~LoginProviderParser();
public:
HRESULT SetReader(obj_xml *pReader);
HRESULT Begin(ifc_xmlreaderparams *params);
HRESULT End(LoginProvider **ppProvider);
protected:
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
protected:
obj_xml *reader;
StringBuilder elementString;
LoginProvider *provider;
LoginTemplateNodeParser templateNodeParser;
LoginCommandNodeParser commandNodeParser;
BOOL hitList[PROVIDER_TAG_MAX];
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGIN_PROVIDER_PARSER_HEADER

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

View File

@@ -0,0 +1,842 @@
#include "./resultWebAuth.h"
#include "./common.h"
#include "./commandWebAuth.h"
#include "./loginData.h"
#include "./dataAddress.h"
#include "./loginCredentials.h"
#include "./loginBox.h"
#include "./loginProvider.h"
#include "./loginStatus.h"
#include "./externalMngr.h"
#include "./browserWindow.h"
#include "../resource.h"
#include "../api.h"
#include "../api_auth.h"
#include "../../omBrowser/obj_ombrowser.h"
#include "../../omBrowser/ifc_ombrowserwndenum.h"
#include "../../omBrowser/ifc_ombrowserwndmngr.h"
#include "../../omBrowser/browserUiCommon.h"
#include "../../winamp/jsapi.h"
#include "../../winamp/jsapi_CallbackParameters.h"
#include <api/service/waservicefactory.h>
#include <strsafe.h>
#define SERVICE_ID 369
#define DISPTABLE_CLASS LoginResultWebAuth
DISPTABLE_BEGIN()
DISPENTRY_ADD(DISPID_LOGINCOMPLETE, L"loginComplete", OnLoginComplete)
DISPENTRY_ADD(DISPID_GETPAGERECT, L"getPageRect", OnGetPageRect)
DISPENTRY_ADD(DISPID_GETBOXRECT, L"getBoxRect", OnGetBoxRect)
DISPENTRY_ADD(DISPID_SETSTATUS, L"setStatus", OnSetStatus)
DISPENTRY_ADD(DISPID_NAVIGATE, L"navigate", OnNavigate)
DISPENTRY_ADD(DISPID_GETSTRING, L"getString", OnGetString)
DISPTABLE_END
#undef DISPTABLE_CLASS
LoginResultWebAuth::LoginResultWebAuth(obj_ombrowser *pManager, LPCWSTR pszTargetUrl, LoginData *pInput, Callback fnCallback, void *pUser)
: ref(1), browserMngr(pManager), external(NULL), targetUrl(NULL), input(pInput), callback(fnCallback), user(pUser),
credentials(NULL), authCode(AUTH_NOT_AUTHORIZED), hView(NULL), completed(NULL),
dispId(DISPID_UNKNOWN), connectionVerified(FALSE), readyUrl(NULL)
{
InitializeCriticalSection(&lock);
targetUrl = LoginBox_CopyString(pszTargetUrl);
input->AddRef();
browserMngr->AddRef();
if(SUCCEEDED(ExternalManager::CreateInstance(&external)))
external->AddDispatch(L"loginBox", this, &dispId);
}
LoginResultWebAuth::~LoginResultWebAuth()
{
hView = NULL;
Finish();
if (NULL != completed)
{
CloseHandle(completed);
}
LoginBox_FreeString(targetUrl);
input->Release();
if (NULL != credentials)
credentials->Release();
LoginBox_FreeString(readyUrl);
DeleteCriticalSection(&lock);
}
HRESULT LoginResultWebAuth::InitBrowserManager(obj_ombrowser **browserMngr)
{
HRESULT hr;
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(OBJ_OmBrowser);
if (NULL == sf) return E_UNEXPECTED;
*browserMngr = (obj_ombrowser*)sf->getInterface();
if (NULL == browserMngr)
hr = E_UNEXPECTED;
else
{
HWND hWinamp = (NULL != WASABI_API_WINAMP) ? WASABI_API_WINAMP->GetMainWindow() : NULL;
if (NULL == hWinamp || FAILED((*browserMngr)->Initialize(NULL, hWinamp)))
{
(*browserMngr)->Release();
hr = E_FAIL;
}
else
{
hr = S_OK;
}
}
sf->Release();
return hr;
}
HRESULT LoginResultWebAuth::CreateInstance(LPCWSTR targetUrl, LoginData *input, Callback callback, void *user, LoginResultWebAuth **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
if (NULL == targetUrl || NULL == input)
return E_INVALIDARG;
obj_ombrowser *browserMngr;
if (FAILED(InitBrowserManager(&browserMngr)))
return E_FAIL;
HRESULT hr;
LoginResultWebAuth *result = new LoginResultWebAuth(browserMngr, targetUrl, input, callback, user);
if (NULL == result)
hr = E_OUTOFMEMORY;
else
{
if (DISPID_UNKNOWN == result->dispId)
hr = E_FAIL;
else
hr = result->Start();
if (FAILED(hr))
{
result->Release();
result = NULL;
}
else
{
*instance = result;
}
}
browserMngr->Release();
return hr;
}
STDMETHODIMP_(ULONG) LoginResultWebAuth::AddRef(void)
{
return InterlockedIncrement((LONG*)&ref);
}
STDMETHODIMP_(ULONG) LoginResultWebAuth::Release(void)
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
STDMETHODIMP LoginResultWebAuth::QueryInterface(REFIID riid, PVOID *ppvObject)
{
if (NULL == ppvObject)
return E_POINTER;
if (IsEqualIID(riid, IFC_OmService))
*ppvObject = static_cast<ifc_omservice*>(this);
else if (IsEqualIID(riid, IFC_OmServiceCommand))
*ppvObject = static_cast<ifc_omservicecommand*>(this);
else if (IsEqualIID(riid, LCUID_WEBAUTH))
*ppvObject = static_cast<LoginResultWebAuth*>(this);
else if (IsEqualIID(riid, IID_IDispatch))
*ppvObject = static_cast<IDispatch*>(this);
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = static_cast<IUnknown*>(reinterpret_cast<LoginResult*>(this));
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
if (NULL == *ppvObject)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
size_t LoginResultWebAuth::Wasabi_AddRef()
{
return AddRef();
}
size_t LoginResultWebAuth::Wasabi_Release()
{
return Release();
}
int LoginResultWebAuth::Wasabi_QueryInterface(GUID iid, void **object)
{
return QueryInterface(iid, object);
}
HRESULT LoginResultWebAuth::Start()
{
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_INITIALIZING));
HWND hParent = input->GetPage();
UINT viewStyle = NBCS_DISABLECONTEXTMENU | NBCS_DIALOGMODE | NBCS_POPUPOWNER |
NBCS_DISABLEFULLSCREEN | NBCS_DISABLEHOSTCSS | NBCS_NOTOOLBAR | NBCS_NOSTATUSBAR;
HRESULT hr = browserMngr->CreateView(this, hParent, NULL, viewStyle, &hView);
if (FAILED(hr))
return hr;
if (FALSE == BrowserWindow_Attach(hView, this))
{
DestroyWindow(hView);
hView = NULL;
hr = E_FAIL;
}
else
{
SetWindowPos(hView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE);
}
return hr;
}
HRESULT LoginResultWebAuth::Finish()
{
EnterCriticalSection(&lock);
if (NULL != external)
{
if (DISPID_UNKNOWN != dispId)
{
external->DeleteMemberByDispID(dispId);
dispId = DISPID_UNKNOWN;
}
external->Release();
external = NULL;
}
// try to destroy windows before browserMngr->Finish() (this will let them to lock less)
if (NULL != hView)
{
DestroyWindow(hView);
hView = NULL;
}
if (NULL != browserMngr)
{
ifc_ombrowserwndmngr *windowMngr;
if (SUCCEEDED(browserMngr->QueryInterface(IFC_OmBrowserWindowManager, (void**)&windowMngr)))
{
ifc_ombrowserwndenum *windowEnum;
if (SUCCEEDED(windowMngr->Enumerate(NULL, NULL, &windowEnum)))
{
HWND hBrowser;
while(S_OK == windowEnum->Next(1, &hBrowser, NULL))
{
if (FALSE != DestroyWindow(hBrowser) && hBrowser == hView)
hView = NULL;
}
windowEnum->Release();
}
windowMngr->Release();
}
}
if (NULL != browserMngr)
{
browserMngr->Finish();
browserMngr->Release();
browserMngr = NULL;
}
LeaveCriticalSection(&lock);
return S_OK;
}
void LoginResultWebAuth::NotifyComplete()
{
Callback callbackCopy(NULL);
HANDLE completedCopy(NULL);
INT statusId;
switch(authCode)
{
case AUTH_SUCCESS: statusId = IDS_STATUS_SUCCEEDED; break;
case AUTH_SECURID: statusId = IDS_STATUS_PASSCODE_REQUIRED; break;
case AUTH_ABORT: statusId = IDS_STATUS_ABORTED; break;
default: statusId = IDS_STATUS_FAILED; break;
}
input->SetStatus(MAKEINTRESOURCE(statusId));
EnterCriticalSection(&lock);
callbackCopy = callback;
if (NULL == completed || FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), &completedCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
completedCopy = NULL;
}
LeaveCriticalSection(&lock);
if (NULL != completedCopy)
{
SetEvent(completedCopy);
CloseHandle(completedCopy);
}
if (NULL != callbackCopy)
callbackCopy(this);
}
HRESULT LoginResultWebAuth::GetWaitHandle(HANDLE *handle)
{
if (NULL == handle)
return E_POINTER;
HRESULT hr = S_OK;
EnterCriticalSection(&lock);
if (NULL == completed)
{
completed = CreateEvent(NULL, TRUE, (S_OK == IsCompleted()), NULL);
if (NULL == completed)
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
}
if (SUCCEEDED(hr) &&
FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginResultWebAuth::GetUser(void **pUser)
{
if (NULL == pUser) return E_POINTER;
*pUser = user;
return S_OK;
}
HRESULT LoginResultWebAuth::RequestAbort(BOOL fDrop)
{
HRESULT hr;
EnterCriticalSection(&lock);
authCode = AUTH_ABORT;
if (NULL == browserMngr)
hr = S_FALSE;
else
{
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_ABORTING));
Finish();
hr = S_OK;
}
if (NULL != credentials)
{
credentials->Release();
credentials = NULL;
}
LeaveCriticalSection(&lock);
if (S_OK == hr)
NotifyComplete();
return hr;
}
HRESULT LoginResultWebAuth::IsCompleted()
{
return (NULL == browserMngr) ? S_OK : S_FALSE;
}
HRESULT LoginResultWebAuth::IsAborting()
{
return E_NOTIMPL;
}
HRESULT LoginResultWebAuth::GetLoginData(LoginData **loginData)
{
if (NULL == loginData) return E_POINTER;
*loginData = input;
if (NULL != input)
input->AddRef();
return S_OK;
}
STDMETHODIMP_(void) LoginResultWebAuth::Event_BrowserReady(HWND hBrowser)
{
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_CONNECTING));
}
STDMETHODIMP_(void) LoginResultWebAuth::Event_DocumentReady(HWND hBrowser)
{
BOOL validateDocument = TRUE;
EnterCriticalSection(&lock);
if (NULL != readyUrl)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, readyUrl, -1, L"loginbox:finish", -1))
{
if (FAILED(BrowserWindow_QueueApc(hView, 0L)))
{
Finish();
NotifyComplete();
}
return;
}
connectionVerified = FALSE;
BrowserControl_Navigate(hBrowser, NAVIGATE_STOP, FALSE);
if (FALSE != BrowserControl_Navigate(hBrowser, readyUrl, TRUE))
validateDocument = FALSE;
LoginBox_FreeString(readyUrl);
readyUrl = NULL;
}
LeaveCriticalSection(&lock);
if (FALSE != validateDocument && FALSE == connectionVerified)
{
// time to kill it
authCode = AUTH_404;
Finish();
NotifyComplete();
}
}
STDMETHODIMP_(void) LoginResultWebAuth::Event_BrowserClosing(HWND hBrowser)
{
}
STDMETHODIMP_(void) LoginResultWebAuth::Event_InvokeApc(HWND hBrowser, LPARAM param)
{
Finish();
NotifyComplete();
}
unsigned int LoginResultWebAuth::GetId()
{
return SERVICE_ID;
}
HRESULT LoginResultWebAuth::GetName(wchar_t *pszBuffer, int cchBufferMax)
{
if (NULL == pszBuffer)
return E_POINTER;
WCHAR szName[128] = {0}, szTemplate[256] = {0};
WASABI_API_LNGSTRINGW_BUF(IDS_WEBAUTH_CAPTION_TEMPLATE, szTemplate, ARRAYSIZE(szTemplate));
LoginProvider *loginProvider;
if (SUCCEEDED(input->GetProvider(&loginProvider)) && NULL != loginProvider)
{
loginProvider->GetName(szName, ARRAYSIZE(szName));
loginProvider->Release();
}
return StringCchPrintf(pszBuffer, cchBufferMax, szTemplate, szName);
}
HRESULT LoginResultWebAuth::GetUrl(wchar_t *pszBuffer, int cchBufferMax)
{
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_CONNECTING));
LPWSTR cursor;
size_t remaining;
HRESULT hr = StringCchCopyEx(pszBuffer, cchBufferMax, targetUrl, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
if (FAILED(hr)) return hr;
LoginDataAddress *inputAddress;
if (SUCCEEDED(input->QueryInterface(IID_LoginDataAddress, (void**)&inputAddress)))
{
LPCWSTR pszAddress = inputAddress->GetAddress();
if (NULL != pszAddress && L'\0' != *pszAddress)
{
LPWSTR paramBegin = cursor;
while (L'?' != *paramBegin && paramBegin != pszBuffer)
paramBegin = CharPrev(pszBuffer, paramBegin);
WCHAR separator = (L'?' == *paramBegin) ? L'&' : L'?';
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, 0, L"%cuserUrl=%s", separator, pszAddress);
}
inputAddress->Release();
}
return hr;
}
HRESULT LoginResultWebAuth::GetExternal(IDispatch **ppDispatch)
{
if (NULL == ppDispatch)
return E_POINTER;
*ppDispatch = external;
if (NULL != external)
external->AddRef();
return S_OK;
}
HRESULT LoginResultWebAuth::QueryState(HWND hBrowser, const GUID *commandGroup, UINT commandId)
{
if (NULL == commandGroup)
return E_NOTIMPL;
if (IsEqualGUID(*commandGroup, CMDGROUP_NAVIGATION))
{
switch(commandId)
{
case NAVCOMMAND_HOME:
return CMDSTATE_DISABLED;
}
}
return E_NOTIMPL;
}
HRESULT LoginResultWebAuth::Exec(HWND hBrowser, const GUID *commandGroup, UINT commandId, ULONG_PTR commandArg)
{
return E_NOTIMPL;
}
HRESULT LoginResultWebAuth::DispParamsToCredentials(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, UINT FAR *puArgErr, HRESULT *errorEx, LPWSTR *finishUrl)
{
if (NULL != finishUrl)
*finishUrl = NULL;
JSAPI_VERIFY_METHOD(wFlags);
JSAPI_VERIFY_PARAMCOUNT_OPTIONAL(pdispparams, 5, 6);
BSTR username;
BSTR token;
BSTR sessionKey;
__time64_t expire;
JSAPI_GETUNSIGNED_AS_NUMBER(authCode, pdispparams, 1, puArgErr);
JSAPI_GETSTRING(token, pdispparams, 2, puArgErr);
JSAPI_GETSTRING(sessionKey, pdispparams, 3, puArgErr);
JSAPI_GETUNSIGNED_AS_NUMBER(expire, pdispparams, 4, puArgErr);
JSAPI_GETSTRING(username, pdispparams, 5, puArgErr);
expire += _time64(0);
if (NULL != finishUrl && pdispparams->cArgs > 5)
{
VARIANTARG *arg = &pdispparams->rgvarg[pdispparams->cArgs - 6];
if (NULL != arg && VT_BSTR == arg->vt)
*finishUrl = LoginBox_CopyString(arg->bstrVal);
}
if (NULL != credentials)
{
credentials->Release();
credentials = NULL;
}
if (AUTH_SUCCESS == authCode)
{
GUID realm;
HRESULT hr = input->GetRealm(&realm);
if (SUCCEEDED(hr))
{
LPSTR sessionAnsi(NULL), tokenAnsi(NULL);
if (FAILED(LoginBox_WideCharToMultiByte(CP_UTF8, 0, sessionKey, -1, NULL, NULL, &sessionAnsi)) ||
FAILED(LoginBox_WideCharToMultiByte(CP_UTF8, 0, token, -1, NULL, NULL, &tokenAnsi)))
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
hr = LoginCredentials::CreateInstance(&realm, username, sessionAnsi, tokenAnsi, expire, &credentials);
LoginBox_FreeAnsiString(sessionAnsi);
LoginBox_FreeAnsiString(tokenAnsi);
}
if (FAILED(hr))
{
if (NULL != errorEx)
*errorEx = hr;
}
}
return S_OK;
}
HRESULT LoginResultWebAuth::OnLoginComplete(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
JSAPI_INIT_RESULT(pvarResult, VT_BOOL);
HRESULT hr, errorEx;
BOOL finishLogin = TRUE;
EnterCriticalSection(&lock);
LPWSTR finishUrl;
hr = DispParamsToCredentials(wFlags, pdispparams, pvarResult, puArgErr, &errorEx, &finishUrl);
JSAPI_SET_RESULT(pvarResult, boolVal, (SUCCEEDED(hr) && SUCCEEDED(errorEx)) ? VARIANT_TRUE : VARIANT_FALSE);
if (NULL != finishUrl && L'\0' != *finishUrl)
{
LoginBox_FreeString(readyUrl);
readyUrl = LoginBox_CopyString(L"loginbox:finish");
if (NULL != readyUrl)
{
if (FALSE == hView || FALSE == BrowserControl_Navigate(hView, finishUrl, FALSE))
{
LoginBox_FreeString(readyUrl);
readyUrl = NULL;
}
else
finishLogin = FALSE;
}
}
LoginBox_FreeString(finishUrl);
LeaveCriticalSection(&lock);
if (FALSE != finishLogin)
{
if (FAILED(BrowserWindow_QueueApc(hView, 0L)))
{
Finish();
NotifyComplete();
}
}
return hr;
}
HRESULT LoginResultWebAuth::OnGetPageRect(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
JSAPI_VERIFY_METHOD(wFlags);
JSAPI_INIT_RESULT(pvarResult, VT_DISPATCH);
RECT rect;
EnterCriticalSection(&lock);
HWND hPage = input->GetPage();
if (NULL == hPage || FALSE == GetWindowRect(hPage, &rect))
SetRectEmpty(&rect);
LeaveCriticalSection(&lock);
JSAPI::CallbackParameters *params = new JSAPI::CallbackParameters;
params->AddLong(L"x", rect.left);
params->AddLong(L"y", rect.top);
params->AddLong(L"cx", rect.right - rect.left);
params->AddLong(L"cy", rect.bottom - rect.top);
V_DISPATCH(pvarResult) = params;
return S_OK;
}
HRESULT LoginResultWebAuth::OnGetBoxRect(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
JSAPI_VERIFY_METHOD(wFlags);
JSAPI_INIT_RESULT(pvarResult, VT_DISPATCH);
RECT rect;
EnterCriticalSection(&lock);
HWND hBox = input->GetLoginbox();
if (NULL == hBox || FALSE == GetWindowRect(hBox, &rect))
SetRectEmpty(&rect);
LeaveCriticalSection(&lock);
if (NULL != pvarResult)
{
JSAPI::CallbackParameters *params = new JSAPI::CallbackParameters;
params->AddLong(L"x", rect.left);
params->AddLong(L"y", rect.top);
params->AddLong(L"cx", rect.right - rect.left);
params->AddLong(L"cy", rect.bottom - rect.top);
V_DISPATCH(pvarResult) = params;
}
return S_OK;
}
HRESULT LoginResultWebAuth::OnSetStatus(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
connectionVerified = TRUE;
JSAPI_VERIFY_METHOD(wFlags);
JSAPI_VERIFY_PARAMCOUNT(pdispparams, 1);
JSAPI_INIT_RESULT(pvarResult, VT_BOOL);
LPCWSTR pszStatus = NULL;
INT paramIndex = pdispparams->cArgs - 1;
VARIANTARG *param = &pdispparams->rgvarg[paramIndex];
switch(param->vt)
{
case VT_I4:
pszStatus = (MAKEINTRESOURCE(param->lVal));
break;
case VT_BSTR:
pszStatus = param->bstrVal;
break;
default:
if (puArgErr) *puArgErr = paramIndex;
return DISP_E_TYPEMISMATCH;
}
HRESULT hr = input->SetStatus(pszStatus);
JSAPI_SET_RESULT(pvarResult, boolVal, (SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE));
return S_OK;
}
HRESULT LoginResultWebAuth::OnNavigate(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
JSAPI_VERIFY_METHOD(wFlags);
JSAPI_VERIFY_PARAMCOUNT_OPTIONAL(pdispparams, 1, 3);
JSAPI_INIT_RESULT(pvarResult, VT_BOOL);
BSTR targetUrl = JSAPI_PARAM_OPTIONAL(pdispparams, 1, bstrVal, NULL);
BSTR callbackUrl = JSAPI_PARAM_OPTIONAL(pdispparams, 2, bstrVal, NULL);
BSTR message = JSAPI_PARAM_OPTIONAL(pdispparams, 3, bstrVal, NULL);
HRESULT hr;
if (NULL == targetUrl || L'\0' == *targetUrl ||
NULL == callbackUrl || L'\0' == *callbackUrl)
{
hr = E_INVALIDARG;
}
else
{
EnterCriticalSection(&lock);
LoginBox_FreeString(readyUrl);
readyUrl = LoginBox_CopyString(callbackUrl);
if (NULL == readyUrl)
hr = E_OUTOFMEMORY;
else
{
connectionVerified = FALSE;
if (NULL == hView || FALSE == BrowserControl_Navigate(hView, targetUrl, FALSE))
{
LoginBox_FreeString(readyUrl);
readyUrl = NULL;
hr = E_FAIL;
}
else
hr = S_OK;
}
LeaveCriticalSection(&lock);
}
JSAPI_SET_RESULT(pvarResult, boolVal, (SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE));
return S_OK;
}
HRESULT LoginResultWebAuth::OnGetString(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, unsigned int FAR *puArgErr)
{
if (0 == ((DISPATCH_METHOD |DISPATCH_PROPERTYGET) &wFlags))
return DISP_E_MEMBERNOTFOUND;
JSAPI_VERIFY_PARAMCOUNT(pdispparams, 1);
JSAPI_INIT_RESULT(pvarResult, VT_BSTR);
UINT stringId;
JSAPI_GETUNSIGNED_AS_NUMBER(stringId, pdispparams, 1, puArgErr);
WCHAR szBuffer[4096] = {0};
BSTR string = SysAllocString(WASABI_API_LNGSTRINGW_BUF(stringId, szBuffer, ARRAYSIZE(szBuffer)));
JSAPI_SET_RESULT(pvarResult, bstrVal, string);
return S_OK;
}
HRESULT LoginResultWebAuth::GetResult(INT *pAuthCode, LoginCredentials **ppCredentials)
{
if (S_OK != IsCompleted())
return E_PENDING;
EnterCriticalSection(&lock);
if (NULL != pAuthCode)
*pAuthCode = authCode;
if (NULL != ppCredentials)
{
*ppCredentials = credentials;
if (NULL != credentials)
credentials->AddRef();
}
LeaveCriticalSection(&lock);
return S_OK;
}
#define CBCLASS LoginResultWebAuth
START_MULTIPATCH;
START_PATCH(MPIID_OMSVC)
M_CB(MPIID_OMSVC, ifc_omservice, ADDREF, Wasabi_AddRef);
M_CB(MPIID_OMSVC, ifc_omservice, RELEASE, Wasabi_Release);
M_CB(MPIID_OMSVC, ifc_omservice, QUERYINTERFACE, Wasabi_QueryInterface);
M_CB(MPIID_OMSVC, ifc_omservice, API_GETID, GetId);
M_CB(MPIID_OMSVC, ifc_omservice, API_GETNAME, GetName);
M_CB(MPIID_OMSVC, ifc_omservice, API_GETURL, GetUrl);
M_CB(MPIID_OMSVC, ifc_omservice, API_GETEXTERNAL, GetExternal);
NEXT_PATCH(MPIID_OMSVCCOMMAND)
M_CB(MPIID_OMSVCCOMMAND, ifc_omservicecommand, ADDREF, Wasabi_AddRef);
M_CB(MPIID_OMSVCCOMMAND, ifc_omservicecommand, RELEASE, Wasabi_Release);
M_CB(MPIID_OMSVCCOMMAND, ifc_omservicecommand, QUERYINTERFACE, Wasabi_QueryInterface);
M_CB(MPIID_OMSVCCOMMAND, ifc_omservicecommand, API_QUERYSTATE, QueryState);
M_CB(MPIID_OMSVCCOMMAND, ifc_omservicecommand, API_EXEC, Exec);
END_PATCH
END_MULTIPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,129 @@
#ifndef NULLSOFT_AUTH_LOGINRESULT_WEBAUTH_HEADER
#define NULLSOFT_AUTH_LOGINRESULT_WEBAUTH_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginResult.h"
#include "./browserEvent.h"
#include "../omBrowser/ifc_omservice.h"
#include "../omBrowser/ifc_omservicecommand.h"
#include "../../nu/dispatchTable.h"
#include <bfc/multipatch.h>
class LoginData;
class LoginCredentials;
class ExternalManager;
class obj_ombrowser;
#define MPIID_OMSVC 10
#define MPIID_OMSVCCOMMAND 20
class LoginResultWebAuth : public LoginResult,
public IDispatch,
public BrowserEvent,
public MultiPatch<MPIID_OMSVC, ifc_omservice>,
public MultiPatch<MPIID_OMSVCCOMMAND, ifc_omservicecommand>
{
public:
typedef enum
{
DISPID_LOGINCOMPLETE = 700,
DISPID_GETPAGERECT = 701,
DISPID_GETBOXRECT = 702,
DISPID_SETSTATUS = 703,
DISPID_NAVIGATE = 704,
DISPID_GETSTRING = 705,
} DispatchCodes;
protected:
LoginResultWebAuth(obj_ombrowser *pManager, LPCWSTR pszTargetUrl, LoginData *pInput, Callback fnCallback, void *pUser);
~LoginResultWebAuth();
public:
static HRESULT CreateInstance(LPCWSTR targetUrl, LoginData *input, Callback callback, void *user, LoginResultWebAuth **instance);
public:
/* IUnknown */
STDMETHOD(QueryInterface)(REFIID riid, PVOID *ppvObject);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
/* IDispatchable */
DISPTABLE_INCLUDE();
DISPHANDLER_REGISTER(OnLoginComplete);
DISPHANDLER_REGISTER(OnGetPageRect);
DISPHANDLER_REGISTER(OnGetBoxRect);
DISPHANDLER_REGISTER(OnSetStatus);
DISPHANDLER_REGISTER(OnNavigate);
DISPHANDLER_REGISTER(OnGetString);
/* LoignResult */
HRESULT GetWaitHandle(HANDLE *handle);
HRESULT GetUser(void **pUser);
HRESULT RequestAbort(BOOL fDrop);
HRESULT IsCompleted();
HRESULT IsAborting();
HRESULT GetLoginData(LoginData **loginData);
/* BrowserEvent */
STDMETHOD_(void, Event_BrowserReady)(HWND hBrowser);
STDMETHOD_(void, Event_DocumentReady)(HWND hBrowser);
STDMETHOD_(void, Event_BrowserClosing)(HWND hBrowser);
STDMETHOD_(void, Event_InvokeApc)(HWND hBrowser, LPARAM param);
protected:
/* Dispatchable */
size_t Wasabi_AddRef();
size_t Wasabi_Release();
int Wasabi_QueryInterface(GUID iid, void **object);
/* ifc_omservice */
unsigned int GetId();
HRESULT GetName(wchar_t *pszBuffer, int cchBufferMax);
HRESULT GetUrl(wchar_t *pszBuffer, int cchBufferMax);
HRESULT GetExternal(IDispatch **ppDispatch);
/* ifc_omservicecommand */
HRESULT QueryState(HWND hBrowser, const GUID *commandGroup, UINT commandId);
HRESULT Exec(HWND hBrowser, const GUID *commandGroup, UINT commandId, ULONG_PTR commandArg);
public:
HRESULT GetResult(INT *authCode, LoginCredentials **credentials);
private:
static HRESULT InitBrowserManager(obj_ombrowser **browserMngr);
HRESULT Start();
HRESULT Finish();
void NotifyComplete();
HRESULT DispParamsToCredentials(WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, UINT FAR *puArgErr, HRESULT *errorEx, LPWSTR *finishUrl);
protected:
ULONG ref;
LoginData *input;
Callback callback;
void *user;
LoginCredentials *credentials;
INT authCode;
obj_ombrowser *browserMngr;
LPWSTR targetUrl;
HWND hView;
CRITICAL_SECTION lock;
HANDLE completed;
ExternalManager *external;
DISPID dispId;
BOOL connectionVerified;
LPWSTR readyUrl;
protected:
RECVS_MULTIPATCH;
};
#endif //NULLSOFT_AUTH_LOGINRESULT_WEBAUTH_HEADER

View File

@@ -0,0 +1,574 @@
#include "./resultWinampAuth.h"
#include "./common.h"
#include "./commandWinampAuth.h"
#include "./loginData.h"
#include "./dataCredentials.h"
#include "./loginCredentials.h"
#include "./loginbox.h"
#include "../resource.h"
LoginResultWinampAuth::LoginResultWinampAuth(api_auth *auth, LoginDataCredentials *pInput, Callback fnCallback, void *pUser)
: ref(1), authApi(auth), input(pInput), callback(fnCallback), user(pUser),
thread(NULL), abort(NULL), completed(NULL), credentials(NULL), authCode(AUTH_NOT_AUTHORIZED), statusCookie(0)
{
InitializeCriticalSection(&lock);
authApi->AddRef();
input->AddRef();
}
LoginResultWinampAuth::~LoginResultWinampAuth()
{
if (NULL != abort)
CloseHandle(abort);
if (NULL != completed)
CloseHandle(completed);
if (NULL != thread)
CloseHandle(thread);
authApi->Release();
input->Release();
if (NULL != credentials)
credentials->Release();
DeleteCriticalSection(&lock);
}
HRESULT LoginResultWinampAuth::CreateInstance(LoginData *input, Callback callback, void *user, LoginResultWinampAuth **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
LoginDataCredentials *credentialsInput;
if (NULL == input || FAILED(input->QueryInterface(IID_LoginDataCredentials, (void**)&credentialsInput)))
return E_INVALIDARG;
HRESULT hr;
api_auth *authApi;
HWND hLoginbox = credentialsInput->GetLoginbox();
if (NULL == hLoginbox || FALSE == LoginBox_GetAuthApi(hLoginbox, &authApi))
hr = E_FAIL;
else
{
LoginResultWinampAuth *result = new LoginResultWinampAuth(authApi, credentialsInput, callback, user);
if (NULL == result)
hr = E_OUTOFMEMORY;
else
{
hr = result->Start();
if (FAILED(hr))
{
result->Release();
result = NULL;
}
else
{
*instance = result;
}
}
authApi->Release();
}
credentialsInput->Release();
return hr;
}
STDMETHODIMP_(ULONG) LoginResultWinampAuth::AddRef(void)
{
return InterlockedIncrement((LONG*)&ref);
}
STDMETHODIMP_(ULONG) LoginResultWinampAuth::Release(void)
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
STDMETHODIMP LoginResultWinampAuth::QueryInterface(REFIID riid, PVOID *ppvObject)
{
if (NULL == ppvObject)
return E_POINTER;
if (IsEqualIID(riid, LCUID_WINAMPAUTH))
*ppvObject = static_cast<LoginResultWinampAuth*>(this);
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = static_cast<IUnknown*>(this);
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
if (NULL == *ppvObject)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
size_t LoginResultWinampAuth::Wasabi_AddRef()
{
return AddRef();
}
size_t LoginResultWinampAuth::Wasabi_Release()
{
return Release();
}
int LoginResultWinampAuth::Wasabi_QueryInterface(GUID iid, void **object)
{
return QueryInterface(iid, object);
}
HRESULT LoginResultWinampAuth::Start()
{
//HRESULT hr;
HANDLE threadCopy = NULL;
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_INITIALIZING));
EnterCriticalSection(&lock);
if (NULL != thread)
{
//hr = E_PENDING;
}
else
{
AddRef();
thread = CreateThread(NULL, 0, WinampAuth_ThreadProcCallback, this, CREATE_SUSPENDED, NULL);
if (NULL == thread)
{
Release();
}
else
{
if (0 == DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &threadCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
ResumeThread(thread); // grr...
threadCopy = NULL;
}
}
}
LeaveCriticalSection(&lock);
if (NULL != threadCopy)
{
ResumeThread(threadCopy);
CloseHandle(threadCopy);
}
return S_OK;
}
DWORD LoginResultWinampAuth::ThreadProc()
{
Callback callbackCopy(NULL);
HANDLE completedCopy(NULL);
INT resultCode = AUTH_SUCCESS;
LPWSTR username(NULL), password(NULL);
api_auth::AuthResults authResults;
SecureZeroMemory(&authResults, sizeof(authResults));
EnterCriticalSection(&lock);
authCode = AUTH_NOT_AUTHORIZED;
if (NULL != credentials)
{
credentials->Release();
credentials = NULL;
}
LeaveCriticalSection(&lock);
username = GetUsername(input->GetUsername(), &resultCode);
if (AUTH_SUCCESS == resultCode)
password = GetPassword(input->GetPassword(), &resultCode);
if (AUTH_SUCCESS == resultCode)
{
if (NULL == input->GetContext())
{
resultCode = authApi->Login(username, password, &authResults, this);
}
else
{
LPWSTR passcode = GetPasscode(input->GetPasscode(), &resultCode);
if (AUTH_SUCCESS == resultCode)
{
resultCode = authApi->LoginSecurID(username, password, input->GetContext(), passcode, &authResults, this);
LoginBox_FreeStringSecure(passcode);
}
}
}
EnterCriticalSection(&lock);
authCode = resultCode;
switch(authCode)
{
case AUTH_SUCCESS:
{
GUID realm;
if (FAILED(input->GetRealm(&realm)) ||
FAILED(LoginCredentials::CreateInstance(&realm, username, authResults.session_key,
authResults.token, authResults.expire, &credentials)))
{
authCode = AUTH_UNEXPECTED;
}
}
break;
case AUTH_SECURID:
if(FAILED(input->SetContext(authResults.context)))
authCode = AUTH_NOT_AUTHORIZED;
break;
}
INT statusId;
switch(authCode)
{
case AUTH_SUCCESS: statusId = IDS_STATUS_SUCCEEDED; break;
case AUTH_SECURID: statusId = IDS_STATUS_PASSCODE_REQUIRED; break;
case AUTH_ABORT: statusId = IDS_STATUS_ABORTED; break;
default: statusId = IDS_STATUS_FAILED; break;
}
input->SetStatus(MAKEINTRESOURCE(statusId));
CloseHandle(thread);
thread = NULL;
callbackCopy = callback;
if (NULL == completed || FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), &completedCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
completedCopy = NULL;
}
LeaveCriticalSection(&lock);
SecureZeroMemory(&authResults, sizeof(authResults));
LoginBox_FreeStringSecure(username);
LoginBox_FreeStringSecure(password);
if (NULL != completedCopy)
{
SetEvent(completedCopy);
CloseHandle(completedCopy);
}
if (NULL != callbackCopy)
callbackCopy(this);
return 0;
}
HRESULT LoginResultWinampAuth::GetWaitHandle(HANDLE *handle)
{
if (NULL == handle)
return E_POINTER;
HRESULT hr = S_OK;
EnterCriticalSection(&lock);
if (NULL == completed)
{
completed = CreateEvent(NULL, TRUE, (S_OK == IsCompleted()), NULL);
if (NULL == completed)
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
}
if (SUCCEEDED(hr) &&
FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginResultWinampAuth::GetUser(void **pUser)
{
if (NULL == pUser) return E_POINTER;
EnterCriticalSection(&lock);
*pUser = user;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginResultWinampAuth::RequestAbort(BOOL fDrop)
{
HRESULT hr;
EnterCriticalSection(&lock);
if (NULL == abort)
{
abort = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == abort)
{
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
}
if (NULL != abort && FALSE == SetEvent(abort))
{
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
else
{
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_ABORTING));
}
if (FALSE != fDrop)
{
callback = NULL;
user = NULL;
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT LoginResultWinampAuth::IsCompleted()
{
return (NULL == thread) ? S_OK : S_FALSE;
}
HRESULT LoginResultWinampAuth::IsAborting()
{
return IsAbortingEx(0);
}
HRESULT LoginResultWinampAuth::IsAbortingEx(UINT waitMs)
{
return (NULL != abort && WAIT_OBJECT_0 == WaitForSingleObjectEx(abort, waitMs, TRUE))?
S_OK : S_FALSE;
}
HRESULT LoginResultWinampAuth::GetLoginData(LoginData **loginData)
{
if (NULL == loginData) return E_POINTER;
EnterCriticalSection(&lock);
*loginData = input;
if (NULL != input)
input->AddRef();
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT LoginResultWinampAuth::GetResult(INT *pAuthCode, LoginCredentials **ppCredentials)
{
if (S_OK != IsCompleted())
return E_PENDING;
EnterCriticalSection(&lock);
if (NULL != pAuthCode)
*pAuthCode = authCode;
if (NULL != ppCredentials)
{
*ppCredentials = credentials;
if (NULL != credentials)
credentials->AddRef();
}
LeaveCriticalSection(&lock);
return S_OK;
}
int LoginResultWinampAuth::Event_AuthConnecting()
{
if (S_OK == IsAbortingEx(0))
return 1;
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_CONNECTING));
return 0;
}
int LoginResultWinampAuth::Event_AuthSending()
{
if (S_OK == IsAbortingEx(0))
return 1;
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_SENDING));
return 0;
}
int LoginResultWinampAuth::Event_AuthReceiving()
{
if (S_OK == IsAbortingEx(0))
return 1;
input->SetStatus(MAKEINTRESOURCE(IDS_STATUS_RECEIVING));
return 0;
}
int LoginResultWinampAuth::Event_AuthIdle()
{
if (S_OK == IsAbortingEx(50))
return 1;
return 0;
}
LPWSTR LoginResultWinampAuth::GetUsername(LPCWSTR pszInput, INT *authError)
{
return MakeAuthParam(pszInput, -1, 3, 48, TRUE, TRUE, (0xFFFF & ~C1_CNTRL), AUTH_USERNAME, authError);
}
LPWSTR LoginResultWinampAuth::GetPassword(LPCWSTR pszInput, INT *authError)
{
return MakeAuthParam(pszInput, -1, 6, 48, TRUE, FALSE, (0xFFFF & ~C1_CNTRL), AUTH_PASSWORD, authError);
}
LPWSTR LoginResultWinampAuth::GetPasscode(LPCWSTR pszInput, INT *authError)
{
return MakeAuthParam(pszInput, -1, 6, 6, FALSE, FALSE, C1_DIGIT, AUTH_PASSCODE, authError);
}
LPWSTR LoginResultWinampAuth::MakeAuthParam(LPCWSTR pszInput, INT cchInput, INT min, INT max, BOOL removeSpaces, BOOL firstLetter, WORD typeMask, INT errorBase, INT *authError)
{
if (cchInput < 0 || NULL == pszInput)
cchInput = (NULL != pszInput) ? lstrlen(pszInput) : 0;
if (cchInput < min || (FALSE == removeSpaces && cchInput > max))
{
if (NULL != authError)
*authError = errorBase + ((cchInput < min) ? AUTHPARAM_TOOSHORT : AUTHPARAM_TOOLONG);
return NULL;
}
WORD *info = (WORD*)calloc(cchInput, sizeof(WORD));
if (NULL == info)
{
if (NULL != authError) *authError = AUTH_UNEXPECTED;
return NULL;
}
if (FALSE == GetStringTypeW(CT_CTYPE1, pszInput, cchInput, info))
{
free(info);
if (NULL != authError) *authError = AUTH_UNEXPECTED;
return NULL;
}
INT error = AUTH_SUCCESS;
LPWSTR dest = NULL;
BOOL firstChecked = FALSE;
INT cchSpaces = 0;
for (INT i = 0; i < cchInput; i++)
{
if (FALSE != removeSpaces && 0 != (C1_SPACE & info[i]))
cchSpaces++;
else if (0 == (typeMask & info[i]))
{
error = errorBase + AUTHPARAM_BADFORMAT;
break;
}
else
{
if (FALSE != firstLetter && FALSE == firstChecked)
{
if (0 == (C1_ALPHA & info[i]))
{
error = errorBase + AUTHPARAM_BADFORMAT;
break;
}
firstChecked = TRUE;
}
}
}
if (AUTH_SUCCESS == error)
{
INT cchTotal = cchInput - cchSpaces;
if (cchTotal < min)
error = errorBase + AUTHPARAM_TOOSHORT;
else if (cchTotal > max)
error = errorBase + AUTHPARAM_TOOLONG;
else
{
dest = LoginBox_MallocString(cchTotal + 1);
if (NULL == dest)
error = AUTH_UNEXPECTED;
else
{
if (FALSE != removeSpaces)
{
LPCWSTR s = pszInput;
LPWSTR d = dest;
for (INT i = 0; i < cchInput; i++, s++)
{
if (0 == (C1_SPACE & info[i]))
{
*d = *s;
d++;
}
}
*d = L'\0';
}
else
{
CopyMemory(dest, pszInput, (cchInput * sizeof(WCHAR)));
dest[cchInput] = L'\0';
}
}
}
}
free(info);
if (NULL != authError)
*authError = error;
return dest;
}
static DWORD WINAPI WinampAuth_ThreadProcCallback(void *param)
{
LoginResultWinampAuth *result =(LoginResultWinampAuth*)param;
if (NULL == result) return 1;
INT exitCode = result->ThreadProc();
result->Release();
return exitCode;
}
#define CBCLASS LoginResultWinampAuth
START_DISPATCH;
CB(ADDREF, Wasabi_AddRef)
CB(RELEASE, Wasabi_Release)
CB(QUERYINTERFACE, Wasabi_QueryInterface)
CB(ONCONNECTING, Event_AuthConnecting)
CB(ONSENDING, Event_AuthSending)
CB(ONRECEIVING, Event_AuthReceiving)
CB(ONIDLE, Event_AuthIdle)
END_DISPATCH;
#undef CBCLASS

View File

@@ -0,0 +1,85 @@
#ifndef NULLSOFT_AUTH_LOGINRESULT_WINAMPAUTH_HEADER
#define NULLSOFT_AUTH_LOGINRESULT_WINAMPAUTH_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "./loginResult.h"
#include "../auth/ifc_authcallback.h"
#include "../auth/api_auth.h"
class LoginData;
class LoginCredentials;
class LoginDataCredentials;
class LoginResultWinampAuth : public LoginResult,
public ifc_authcallback
{
protected:
LoginResultWinampAuth(api_auth *auth, LoginDataCredentials *pInput, Callback callback, void *user);
~LoginResultWinampAuth();
public:
static HRESULT CreateInstance(LoginData *input, Callback callback, void *user, LoginResultWinampAuth **instance);
public:
/* IUnknown */
STDMETHOD(QueryInterface)(REFIID riid, PVOID *ppvObject);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
/* LoginResult */
HRESULT GetWaitHandle(HANDLE *handle);
HRESULT GetUser(void **pUser);
HRESULT RequestAbort(BOOL fDrop);
HRESULT IsCompleted();
HRESULT IsAborting();
HRESULT GetLoginData(LoginData **loginData);
public:
HRESULT GetResult(INT *authCode, LoginCredentials **credentials);
protected:
/* Dispatchable */
size_t Wasabi_AddRef();
size_t Wasabi_Release();
int Wasabi_QueryInterface(GUID iid, void **object);
/*ifc_authcallback*/
int Event_AuthConnecting();
int Event_AuthSending();
int Event_AuthReceiving();
int Event_AuthIdle();
private:
HRESULT Start();
DWORD ThreadProc();
HRESULT IsAbortingEx(UINT waitMs);
LPWSTR MakeAuthParam(LPCWSTR pszInput, INT cchInput, INT min, INT max, BOOL removeSpaces, BOOL firstLetter, WORD typeMask, INT errorBase, INT *authError);
LPWSTR GetUsername(LPCWSTR pszInput, INT *authError);
LPWSTR GetPassword(LPCWSTR pszInput, INT *authError);
LPWSTR GetPasscode(LPCWSTR pszInput, INT *authError);
friend static DWORD WINAPI WinampAuth_ThreadProcCallback(void *param);
protected:
ULONG ref;
LoginDataCredentials *input;
Callback callback;
void *user;
api_auth *authApi;
HANDLE thread;
HANDLE abort;
HANDLE completed;
LoginCredentials *credentials;
INT authCode;
CRITICAL_SECTION lock;
UINT statusCookie;
protected:
RECVS_DISPATCH;
};
#endif //NULLSOFT_AUTH_LOGINRESULT_WINAMPAUTH_HEADER

View File

@@ -0,0 +1,85 @@
#include "./common.h"
#include "./stringBuilder.h"
#include <strsafe.h>
StringBuilder::StringBuilder()
: buffer(NULL), cursor(NULL), allocated(0), remaining(0)
{
}
StringBuilder::~StringBuilder()
{
LoginBox_FreeString(buffer);
}
HRESULT StringBuilder::Allocate(size_t newSize)
{
if (newSize <= allocated)
return S_FALSE;
LPWSTR t = LoginBox_ReAllocString(buffer, newSize);
if (NULL == t) return E_OUTOFMEMORY;
cursor = t + (cursor - buffer);
buffer = t;
remaining += newSize - allocated;
allocated = newSize;
return S_OK;
}
void StringBuilder::Clear(void)
{
if (NULL != buffer)
{
buffer[0] = L'\0';
}
cursor = buffer;
remaining = allocated;
}
LPCWSTR StringBuilder::Get(void)
{
return buffer;
}
HRESULT StringBuilder::Set(size_t index, WCHAR value)
{
if (NULL == buffer)
return E_POINTER;
if (index >= allocated)
return E_INVALIDARG;
buffer[index] = value;
return S_OK;
}
HRESULT StringBuilder::Append(LPCWSTR pszString)
{
HRESULT hr;
if (NULL == buffer)
{
hr = Allocate(1024);
if (FAILED(hr)) return hr;
}
size_t cchCursor = remaining;
hr = StringCchCopyEx(cursor, cchCursor, pszString, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
{
size_t offset = cchCursor - remaining;
size_t requested = lstrlen(pszString) + (allocated - remaining) + 1;
size_t newsize = allocated * 2;
while (newsize < requested) newsize = newsize * 2;
hr = Allocate(newsize);
if (FAILED(hr)) return hr;
hr = StringCchCopyEx(cursor, remaining, pszString + offset, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
}
return hr;
}

Some files were not shown because too many files have changed in this diff Show More