mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 22:12:46 +00:00
28e277b65f
Invalidating and updating the whole window is a waste of computation resources and may cause certain controls notably the text string control to flicker. So instead, just invalidate the specific portion of the client area which is the animation bar.
1604 lines
44 KiB
C
1604 lines
44 KiB
C
/*
|
|
* PROJECT: ReactOS msgina.dll
|
|
* FILE: dll/win32/msgina/gui.c
|
|
* PURPOSE: ReactOS Logon GINA DLL
|
|
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
|
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
*/
|
|
|
|
#include "msgina.h"
|
|
|
|
#include <wingdi.h>
|
|
#include <winnls.h>
|
|
#include <winreg.h>
|
|
|
|
typedef struct _DISPLAYSTATUSMSG
|
|
{
|
|
PGINA_CONTEXT Context;
|
|
HDESK hDesktop;
|
|
DWORD dwOptions;
|
|
PWSTR pTitle;
|
|
PWSTR pMessage;
|
|
HANDLE StartupEvent;
|
|
} DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
|
|
|
|
typedef struct _LEGALNOTICEDATA
|
|
{
|
|
LPWSTR pszCaption;
|
|
LPWSTR pszText;
|
|
} LEGALNOTICEDATA, *PLEGALNOTICEDATA;
|
|
|
|
// Timer ID for the animated dialog bar.
|
|
#define IDT_BAR 1
|
|
|
|
typedef struct _DLG_DATA
|
|
{
|
|
PGINA_CONTEXT pgContext;
|
|
HBITMAP hLogoBitmap;
|
|
HBITMAP hBarBitmap;
|
|
HWND hWndBarCtrl;
|
|
DWORD BarCounter;
|
|
DWORD LogoWidth;
|
|
DWORD LogoHeight;
|
|
DWORD BarWidth;
|
|
DWORD BarHeight;
|
|
} DLG_DATA, *PDLG_DATA;
|
|
|
|
static PDLG_DATA
|
|
DlgData_Create(HWND hwndDlg, PGINA_CONTEXT pgContext)
|
|
{
|
|
PDLG_DATA pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pDlgData));
|
|
if (pDlgData)
|
|
{
|
|
pDlgData->pgContext = pgContext;
|
|
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
|
|
}
|
|
return pDlgData;
|
|
}
|
|
|
|
static BOOL
|
|
DlgData_LoadBitmaps(PDLG_DATA pDlgData)
|
|
{
|
|
BITMAP bm;
|
|
|
|
if (!pDlgData)
|
|
return FALSE;
|
|
|
|
pDlgData->hLogoBitmap = LoadImageW(pDlgData->pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP,
|
|
0, 0, LR_DEFAULTCOLOR);
|
|
GetObject(pDlgData->hLogoBitmap, sizeof(bm), &bm);
|
|
pDlgData->LogoWidth = bm.bmWidth;
|
|
pDlgData->LogoHeight = bm.bmHeight;
|
|
|
|
pDlgData->hBarBitmap = LoadImageW(hDllInstance, MAKEINTRESOURCEW(IDI_BAR),
|
|
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
|
GetObject(pDlgData->hBarBitmap, sizeof(bm), &bm);
|
|
pDlgData->BarWidth = bm.bmWidth;
|
|
pDlgData->BarHeight = bm.bmHeight;
|
|
|
|
return (pDlgData->hLogoBitmap != NULL && pDlgData->hBarBitmap != NULL);
|
|
}
|
|
|
|
static void
|
|
DlgData_Destroy(PDLG_DATA pDlgData)
|
|
{
|
|
if (!pDlgData)
|
|
return;
|
|
|
|
DeleteObject(pDlgData->hLogoBitmap);
|
|
DeleteObject(pDlgData->hBarBitmap);
|
|
HeapFree(GetProcessHeap(), 0, pDlgData);
|
|
}
|
|
|
|
static BOOL
|
|
GUIInitialize(
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
TRACE("GUIInitialize(%p)\n", pgContext);
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
SetWelcomeText(HWND hWnd)
|
|
{
|
|
PWCHAR pBuffer = NULL, p;
|
|
HKEY hKey;
|
|
DWORD BufSize, dwType, dwWelcomeSize, dwTitleLength;
|
|
LONG rc;
|
|
|
|
TRACE("SetWelcomeText(%p)\n", hWnd);
|
|
|
|
/* Open the Winlogon key */
|
|
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegOpenKeyExW() failed with error %lu\n", rc);
|
|
return;
|
|
}
|
|
|
|
/* Get the size of the Welcome value */
|
|
dwWelcomeSize = 0;
|
|
rc = RegQueryValueExW(hKey,
|
|
L"Welcome",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwWelcomeSize);
|
|
if (rc == ERROR_FILE_NOT_FOUND || dwWelcomeSize == 0 || dwType != REG_SZ)
|
|
goto done;
|
|
|
|
dwTitleLength = GetWindowTextLengthW(hWnd);
|
|
BufSize = dwWelcomeSize + ((dwTitleLength + 1) * sizeof(WCHAR));
|
|
|
|
pBuffer = HeapAlloc(GetProcessHeap(), 0, BufSize);
|
|
if (pBuffer == NULL)
|
|
goto done;
|
|
|
|
GetWindowTextW(hWnd, pBuffer, BufSize / sizeof(WCHAR));
|
|
wcscat(pBuffer, L" ");
|
|
p = &pBuffer[dwTitleLength + 1];
|
|
|
|
RegQueryValueExW(hKey,
|
|
L"Welcome",
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)p,
|
|
&dwWelcomeSize);
|
|
|
|
SetWindowText(hWnd, pBuffer);
|
|
|
|
done:
|
|
if (pBuffer != NULL)
|
|
HeapFree(GetProcessHeap(), 0, pBuffer);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
StatusDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PDLG_DATA pDlgData;
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
|
|
if (!msg)
|
|
return FALSE;
|
|
|
|
msg->Context->hStatusWindow = hwndDlg;
|
|
|
|
if (msg->pTitle)
|
|
SetWindowTextW(hwndDlg, msg->pTitle);
|
|
SetDlgItemTextW(hwndDlg, IDC_STATUS_MESSAGE, msg->pMessage);
|
|
SetEvent(msg->StartupEvent);
|
|
|
|
pDlgData = DlgData_Create(hwndDlg, msg->Context);
|
|
if (pDlgData == NULL)
|
|
return FALSE;
|
|
|
|
if (DlgData_LoadBitmaps(pDlgData))
|
|
{
|
|
if (SetTimer(hwndDlg, IDT_BAR, 20, NULL) == 0)
|
|
{
|
|
ERR("SetTimer(IDT_BAR) failed: %d\n", GetLastError());
|
|
}
|
|
|
|
/* Get the animation bar control */
|
|
pDlgData->hWndBarCtrl = GetDlgItem(hwndDlg, IDC_BAR);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_TIMER:
|
|
{
|
|
if (pDlgData && pDlgData->hBarBitmap)
|
|
{
|
|
/*
|
|
* Default rotation bar image width is 413 (same as logo)
|
|
* We can divide 413 by 7 without remainder
|
|
*/
|
|
pDlgData->BarCounter = (pDlgData->BarCounter + 7) % pDlgData->BarWidth;
|
|
InvalidateRect(pDlgData->hWndBarCtrl, NULL, FALSE);
|
|
UpdateWindow(pDlgData->hWndBarCtrl);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
LPDRAWITEMSTRUCT lpDis = (LPDRAWITEMSTRUCT)lParam;
|
|
|
|
if (lpDis->CtlID != IDC_BAR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pDlgData && pDlgData->hBarBitmap)
|
|
{
|
|
HDC hdcMem;
|
|
HGDIOBJ hOld;
|
|
DWORD off = pDlgData->BarCounter;
|
|
DWORD iw = pDlgData->BarWidth;
|
|
DWORD ih = pDlgData->BarHeight;
|
|
|
|
hdcMem = CreateCompatibleDC(lpDis->hDC);
|
|
hOld = SelectObject(hdcMem, pDlgData->hBarBitmap);
|
|
BitBlt(lpDis->hDC, off, 0, iw - off, ih, hdcMem, 0, 0, SRCCOPY);
|
|
BitBlt(lpDis->hDC, 0, 0, off, ih, hdcMem, iw - off, 0, SRCCOPY);
|
|
SelectObject(hdcMem, hOld);
|
|
DeleteDC(hdcMem);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
if (pDlgData && pDlgData->hBarBitmap)
|
|
{
|
|
KillTimer(hwndDlg, IDT_BAR);
|
|
}
|
|
DlgData_Destroy(pDlgData);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static DWORD WINAPI
|
|
StartupWindowThread(LPVOID lpParam)
|
|
{
|
|
HDESK hDesk;
|
|
PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
|
|
|
|
/* When SetThreadDesktop is called the system closes the desktop handle when needed
|
|
so we have to create a new handle because this handle may still be in use by winlogon */
|
|
if (!DuplicateHandle ( GetCurrentProcess(),
|
|
msg->hDesktop,
|
|
GetCurrentProcess(),
|
|
(HANDLE*)&hDesk,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS))
|
|
{
|
|
ERR("Duplicating handle failed!\n");
|
|
HeapFree(GetProcessHeap(), 0, lpParam);
|
|
return FALSE;
|
|
}
|
|
|
|
if(!SetThreadDesktop(hDesk))
|
|
{
|
|
ERR("Setting thread desktop failed!\n");
|
|
HeapFree(GetProcessHeap(), 0, lpParam);
|
|
return FALSE;
|
|
}
|
|
|
|
DialogBoxParamW(
|
|
hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_STATUS),
|
|
GetDesktopWindow(),
|
|
StatusDialogProc,
|
|
(LPARAM)lpParam);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpParam);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL
|
|
GUIDisplayStatusMessage(
|
|
IN PGINA_CONTEXT pgContext,
|
|
IN HDESK hDesktop,
|
|
IN DWORD dwOptions,
|
|
IN PWSTR pTitle,
|
|
IN PWSTR pMessage)
|
|
{
|
|
PDISPLAYSTATUSMSG msg;
|
|
HANDLE Thread;
|
|
DWORD ThreadId;
|
|
|
|
TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
|
|
|
|
if (!pgContext->hStatusWindow)
|
|
{
|
|
/*
|
|
* If everything goes correctly, 'msg' is freed
|
|
* by the 'StartupWindowThread' thread.
|
|
*/
|
|
msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(*msg));
|
|
if(!msg)
|
|
return FALSE;
|
|
|
|
msg->Context = pgContext;
|
|
msg->dwOptions = dwOptions;
|
|
msg->pTitle = pTitle;
|
|
msg->pMessage = pMessage;
|
|
msg->hDesktop = hDesktop;
|
|
|
|
msg->StartupEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
|
|
|
if (!msg->StartupEvent)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, msg);
|
|
return FALSE;
|
|
}
|
|
|
|
Thread = CreateThread(NULL,
|
|
0,
|
|
StartupWindowThread,
|
|
(PVOID)msg,
|
|
0,
|
|
&ThreadId);
|
|
if (Thread)
|
|
{
|
|
/* 'msg' will be freed by 'StartupWindowThread' */
|
|
|
|
CloseHandle(Thread);
|
|
WaitForSingleObject(msg->StartupEvent, INFINITE);
|
|
CloseHandle(msg->StartupEvent);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The 'StartupWindowThread' thread couldn't be created,
|
|
* so we need to free the allocated 'msg'.
|
|
*/
|
|
HeapFree(GetProcessHeap(), 0, msg);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (pTitle)
|
|
SetWindowTextW(pgContext->hStatusWindow, pTitle);
|
|
|
|
SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUS_MESSAGE, pMessage);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL
|
|
GUIRemoveStatusMessage(
|
|
IN PGINA_CONTEXT pgContext)
|
|
{
|
|
if (pgContext->hStatusWindow)
|
|
{
|
|
EndDialog(pgContext->hStatusWindow, 0);
|
|
pgContext->hStatusWindow = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static INT_PTR CALLBACK
|
|
WelcomeDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PDLG_DATA pDlgData;
|
|
|
|
pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pDlgData = DlgData_Create(hwndDlg, (PGINA_CONTEXT)lParam);
|
|
if (pDlgData == NULL)
|
|
return FALSE;
|
|
|
|
DlgData_LoadBitmaps(pDlgData);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
if (pDlgData && pDlgData->hLogoBitmap)
|
|
{
|
|
BeginPaint(hwndDlg, &ps);
|
|
DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hLogoBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
|
|
EndPaint(hwndDlg, &ps);
|
|
}
|
|
return TRUE;
|
|
}
|
|
case WM_DESTROY:
|
|
{
|
|
DlgData_Destroy(pDlgData);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static VOID
|
|
GUIDisplaySASNotice(
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
TRACE("GUIDisplaySASNotice()\n");
|
|
|
|
/* Display the notice window */
|
|
pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_WELCOME),
|
|
GetDesktopWindow(),
|
|
WelcomeDialogProc,
|
|
(LPARAM)pgContext);
|
|
}
|
|
|
|
/* Get the text contained in a textbox. Allocates memory in pText
|
|
* to contain the text. Returns TRUE in case of success */
|
|
static BOOL
|
|
GetTextboxText(
|
|
IN HWND hwndDlg,
|
|
IN INT TextboxId,
|
|
OUT LPWSTR *pText)
|
|
{
|
|
LPWSTR Text;
|
|
int Count;
|
|
|
|
Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
|
|
Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
|
|
if (!Text)
|
|
return FALSE;
|
|
if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, Text);
|
|
return FALSE;
|
|
}
|
|
*pText = Text;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static
|
|
INT
|
|
ResourceMessageBox(
|
|
IN PGINA_CONTEXT pgContext,
|
|
IN HWND hwnd,
|
|
IN UINT uType,
|
|
IN UINT uCaption,
|
|
IN UINT uText)
|
|
{
|
|
WCHAR szCaption[256];
|
|
WCHAR szText[256];
|
|
|
|
LoadStringW(pgContext->hDllInstance, uCaption, szCaption, _countof(szCaption));
|
|
LoadStringW(pgContext->hDllInstance, uText, szText, _countof(szText));
|
|
|
|
return pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
|
|
hwnd,
|
|
szText,
|
|
szCaption,
|
|
uType);
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
DoChangePassword(
|
|
IN PGINA_CONTEXT pgContext,
|
|
IN HWND hwndDlg)
|
|
{
|
|
WCHAR UserName[256];
|
|
WCHAR Domain[256];
|
|
WCHAR OldPassword[256];
|
|
WCHAR NewPassword1[256];
|
|
WCHAR NewPassword2[256];
|
|
PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
|
|
PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
|
|
ULONG RequestBufferSize;
|
|
ULONG ResponseBufferSize = 0;
|
|
LPWSTR Ptr;
|
|
BOOL res = FALSE;
|
|
NTSTATUS ProtocolStatus;
|
|
NTSTATUS Status;
|
|
|
|
GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, _countof(UserName));
|
|
GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, _countof(Domain));
|
|
GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, _countof(OldPassword));
|
|
GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, _countof(NewPassword1));
|
|
GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, _countof(NewPassword2));
|
|
|
|
/* Compare the two passwords and fail if they do not match */
|
|
if (wcscmp(NewPassword1, NewPassword2) != 0)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
IDS_CHANGEPWDTITLE,
|
|
IDS_NONMATCHINGPASSWORDS);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Calculate the request buffer size */
|
|
RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
|
|
((wcslen(Domain) + 1) * sizeof(WCHAR)) +
|
|
((wcslen(UserName) + 1) * sizeof(WCHAR)) +
|
|
((wcslen(OldPassword) + 1) * sizeof(WCHAR)) +
|
|
((wcslen(NewPassword1) + 1) * sizeof(WCHAR));
|
|
|
|
/* Allocate the request buffer */
|
|
RequestBuffer = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
RequestBufferSize);
|
|
if (RequestBuffer == NULL)
|
|
{
|
|
ERR("HeapAlloc failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize the request buffer */
|
|
RequestBuffer->MessageType = MsV1_0ChangePassword;
|
|
RequestBuffer->Impersonating = TRUE;
|
|
|
|
Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
|
|
|
|
/* Pack the domain name */
|
|
RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR);
|
|
RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
|
|
RequestBuffer->DomainName.Buffer = Ptr;
|
|
|
|
RtlCopyMemory(RequestBuffer->DomainName.Buffer,
|
|
Domain,
|
|
RequestBuffer->DomainName.MaximumLength);
|
|
|
|
Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
|
|
|
|
/* Pack the user name */
|
|
RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR);
|
|
RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
|
|
RequestBuffer->AccountName.Buffer = Ptr;
|
|
|
|
RtlCopyMemory(RequestBuffer->AccountName.Buffer,
|
|
UserName,
|
|
RequestBuffer->AccountName.MaximumLength);
|
|
|
|
Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
|
|
|
|
/* Pack the old password */
|
|
RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR);
|
|
RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
|
|
RequestBuffer->OldPassword.Buffer = Ptr;
|
|
|
|
RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
|
|
OldPassword,
|
|
RequestBuffer->OldPassword.MaximumLength);
|
|
|
|
Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
|
|
|
|
/* Pack the new password */
|
|
RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR);
|
|
RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
|
|
RequestBuffer->NewPassword.Buffer = Ptr;
|
|
|
|
RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
|
|
NewPassword1,
|
|
RequestBuffer->NewPassword.MaximumLength);
|
|
|
|
/* Connect to the LSA server */
|
|
if (ConnectToLsa(pgContext) != ERROR_SUCCESS)
|
|
{
|
|
ERR("ConnectToLsa() failed\n");
|
|
goto done;
|
|
}
|
|
|
|
/* Call the authentication package */
|
|
Status = LsaCallAuthenticationPackage(pgContext->LsaHandle,
|
|
pgContext->AuthenticationPackage,
|
|
RequestBuffer,
|
|
RequestBufferSize,
|
|
(PVOID*)&ResponseBuffer,
|
|
&ResponseBufferSize,
|
|
&ProtocolStatus);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
if (!NT_SUCCESS(ProtocolStatus))
|
|
{
|
|
TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus);
|
|
goto done;
|
|
}
|
|
|
|
res = TRUE;
|
|
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
IDS_CHANGEPWDTITLE,
|
|
IDS_PASSWORDCHANGED);
|
|
|
|
if ((wcscmp(UserName, pgContext->UserName) == 0) &&
|
|
(wcscmp(Domain, pgContext->DomainName) == 0) &&
|
|
(wcscmp(OldPassword, pgContext->Password) == 0))
|
|
{
|
|
ZeroMemory(pgContext->Password, sizeof(pgContext->Password));
|
|
wcscpy(pgContext->Password, NewPassword1);
|
|
}
|
|
|
|
done:
|
|
if (RequestBuffer != NULL)
|
|
HeapFree(GetProcessHeap(), 0, RequestBuffer);
|
|
|
|
if (ResponseBuffer != NULL)
|
|
LsaFreeReturnBuffer(ResponseBuffer);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
ChangePasswordDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PGINA_CONTEXT pgContext;
|
|
|
|
pgContext = (PGINA_CONTEXT)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pgContext = (PGINA_CONTEXT)lParam;
|
|
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pgContext);
|
|
|
|
SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, pgContext->UserName);
|
|
SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_ADDSTRING, 0, (LPARAM)pgContext->DomainName);
|
|
SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_SETCURSEL, 0, 0);
|
|
SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
if (DoChangePassword(pgContext, hwndDlg))
|
|
{
|
|
EndDialog(hwndDlg, TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NULL);
|
|
SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NULL);
|
|
SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
|
|
}
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwndDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static VOID
|
|
OnInitSecurityDlg(HWND hwnd,
|
|
PGINA_CONTEXT pgContext)
|
|
{
|
|
WCHAR Buffer1[256];
|
|
WCHAR Buffer2[256];
|
|
WCHAR Buffer3[256];
|
|
WCHAR Buffer4[512];
|
|
|
|
LoadStringW(pgContext->hDllInstance, IDS_LOGONMSG, Buffer1, _countof(Buffer1));
|
|
|
|
wsprintfW(Buffer2, L"%s\\%s", pgContext->DomainName, pgContext->UserName);
|
|
wsprintfW(Buffer4, Buffer1, Buffer2);
|
|
|
|
SetDlgItemTextW(hwnd, IDC_SECURITY_MESSAGE, Buffer4);
|
|
|
|
LoadStringW(pgContext->hDllInstance, IDS_LOGONDATE, Buffer1, _countof(Buffer1));
|
|
|
|
GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
|
|
(SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer2, _countof(Buffer2));
|
|
|
|
GetTimeFormatW(LOCALE_USER_DEFAULT, 0,
|
|
(SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer3, _countof(Buffer3));
|
|
|
|
wsprintfW(Buffer4, Buffer1, Buffer2, Buffer3);
|
|
|
|
SetDlgItemTextW(hwnd, IDC_SECURITY_LOGONDATE, Buffer4);
|
|
|
|
if (pgContext->bAutoAdminLogon)
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SECURITY_LOGOFF), FALSE);
|
|
}
|
|
|
|
|
|
static BOOL
|
|
OnChangePassword(
|
|
IN HWND hwnd,
|
|
IN PGINA_CONTEXT pgContext)
|
|
{
|
|
INT res;
|
|
|
|
TRACE("OnChangePassword()\n");
|
|
|
|
res = pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_CHANGEPWD),
|
|
hwnd,
|
|
ChangePasswordDialogProc,
|
|
(LPARAM)pgContext);
|
|
|
|
TRACE("Result: %x\n", res);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
LogOffDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDYES:
|
|
EndDialog(hwndDlg, IDYES);
|
|
return TRUE;
|
|
|
|
case IDNO:
|
|
EndDialog(hwndDlg, IDNO);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwndDlg, IDNO);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static
|
|
INT
|
|
OnLogOff(
|
|
IN HWND hwndDlg,
|
|
IN PGINA_CONTEXT pgContext)
|
|
{
|
|
return pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_LOGOFF),
|
|
hwndDlg,
|
|
LogOffDialogProc,
|
|
(LPARAM)pgContext);
|
|
}
|
|
|
|
|
|
static
|
|
INT
|
|
OnShutDown(
|
|
IN HWND hwndDlg,
|
|
IN PGINA_CONTEXT pgContext)
|
|
{
|
|
INT ret;
|
|
DWORD ShutdownOptions;
|
|
|
|
TRACE("OnShutDown(%p %p)\n", hwndDlg, pgContext);
|
|
|
|
pgContext->nShutdownAction = GetDefaultShutdownSelState();
|
|
ShutdownOptions = GetDefaultShutdownOptions();
|
|
|
|
if (pgContext->UserToken != NULL)
|
|
{
|
|
if (ImpersonateLoggedOnUser(pgContext->UserToken))
|
|
{
|
|
pgContext->nShutdownAction = LoadShutdownSelState();
|
|
ShutdownOptions = GetAllowedShutdownOptions();
|
|
RevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
|
|
}
|
|
}
|
|
|
|
ret = ShutdownDialog(hwndDlg, ShutdownOptions, pgContext);
|
|
|
|
if (ret == IDOK)
|
|
{
|
|
if (pgContext->UserToken != NULL)
|
|
{
|
|
if (ImpersonateLoggedOnUser(pgContext->UserToken))
|
|
{
|
|
SaveShutdownSelState(pgContext->nShutdownAction);
|
|
RevertToSelf();
|
|
}
|
|
else
|
|
{
|
|
ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
SecurityDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PGINA_CONTEXT pgContext;
|
|
|
|
pgContext = (PGINA_CONTEXT)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pgContext = (PGINA_CONTEXT)lParam;
|
|
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pgContext);
|
|
|
|
SetWelcomeText(hwndDlg);
|
|
|
|
OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
|
|
SetFocus(GetDlgItem(hwndDlg, IDNO));
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_SECURITY_LOCK:
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
|
|
return TRUE;
|
|
case IDC_SECURITY_LOGOFF:
|
|
if (OnLogOff(hwndDlg, pgContext) == IDYES)
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
|
|
return TRUE;
|
|
case IDC_SECURITY_SHUTDOWN:
|
|
if (OnShutDown(hwndDlg, pgContext) == IDOK)
|
|
EndDialog(hwndDlg, pgContext->nShutdownAction);
|
|
return TRUE;
|
|
case IDC_SECURITY_CHANGEPWD:
|
|
if (OnChangePassword(hwndDlg, pgContext))
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
|
|
return TRUE;
|
|
case IDC_SECURITY_TASKMGR:
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
|
|
return TRUE;
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
case WM_CLOSE:
|
|
{
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static INT
|
|
GUILoggedOnSAS(
|
|
IN OUT PGINA_CONTEXT pgContext,
|
|
IN DWORD dwSasType)
|
|
{
|
|
INT result;
|
|
|
|
TRACE("GUILoggedOnSAS()\n");
|
|
|
|
if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
|
|
{
|
|
/* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
|
|
* close itself thanks to the use of WlxDialogBoxParam */
|
|
return WLX_SAS_ACTION_NONE;
|
|
}
|
|
|
|
pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
|
|
pgContext->hWlx);
|
|
|
|
result = pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_SECURITY),
|
|
GetDesktopWindow(),
|
|
SecurityDialogProc,
|
|
(LPARAM)pgContext);
|
|
|
|
if (result < WLX_SAS_ACTION_LOGON ||
|
|
result > WLX_SAS_ACTION_SWITCH_CONSOLE)
|
|
{
|
|
result = WLX_SAS_ACTION_NONE;
|
|
}
|
|
|
|
if (result == WLX_SAS_ACTION_NONE)
|
|
{
|
|
pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
|
|
pgContext->hWlx);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
DoLogon(
|
|
IN HWND hwndDlg,
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
LPWSTR UserName = NULL;
|
|
LPWSTR Password = NULL;
|
|
LPWSTR Domain = NULL;
|
|
BOOL result = FALSE;
|
|
NTSTATUS Status, SubStatus = STATUS_SUCCESS;
|
|
|
|
if (GetTextboxText(hwndDlg, IDC_LOGON_USERNAME, &UserName) && *UserName == '\0')
|
|
goto done;
|
|
|
|
if (GetTextboxText(hwndDlg, IDC_LOGON_DOMAIN, &Domain) && *Domain == '\0')
|
|
goto done;
|
|
|
|
if (!GetTextboxText(hwndDlg, IDC_LOGON_PASSWORD, &Password))
|
|
goto done;
|
|
|
|
Status = DoLoginTasks(pgContext, UserName, Domain, Password, &SubStatus);
|
|
if (Status == STATUS_LOGON_FAILURE)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
IDS_LOGONTITLE,
|
|
IDS_LOGONWRONGUSERORPWD);
|
|
goto done;
|
|
}
|
|
else if (Status == STATUS_ACCOUNT_RESTRICTION)
|
|
{
|
|
TRACE("DoLoginTasks failed! Status 0x%08lx SubStatus 0x%08lx\n", Status, SubStatus);
|
|
|
|
if (SubStatus == STATUS_ACCOUNT_DISABLED)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
IDS_LOGONTITLE,
|
|
IDS_LOGONUSERDISABLED);
|
|
goto done;
|
|
}
|
|
else if (SubStatus == STATUS_ACCOUNT_LOCKED_OUT)
|
|
{
|
|
TRACE("Account locked!\n");
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONERROR,
|
|
IDS_LOGONTITLE,
|
|
IDS_ACCOUNTLOCKED);
|
|
goto done;
|
|
}
|
|
else if ((SubStatus == STATUS_PASSWORD_MUST_CHANGE) ||
|
|
(SubStatus == STATUS_PASSWORD_EXPIRED))
|
|
{
|
|
if (SubStatus == STATUS_PASSWORD_MUST_CHANGE)
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONSTOP,
|
|
IDS_LOGONTITLE,
|
|
IDS_PASSWORDMUSTCHANGE);
|
|
else
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONSTOP,
|
|
IDS_LOGONTITLE,
|
|
IDS_PASSWORDEXPIRED);
|
|
|
|
if (!OnChangePassword(hwndDlg,
|
|
pgContext))
|
|
goto done;
|
|
|
|
Status = DoLoginTasks(pgContext,
|
|
pgContext->UserName,
|
|
pgContext->DomainName,
|
|
pgContext->Password,
|
|
&SubStatus);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("Login after password change failed! (Status 0x%08lx)\n", Status);
|
|
|
|
goto done;
|
|
}
|
|
}
|
|
else if (SubStatus == STATUS_ACCOUNT_EXPIRED)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
IDS_LOGONTITLE,
|
|
IDS_ACCOUNTEXPIRED);
|
|
}
|
|
else if (SubStatus == STATUS_INVALID_LOGON_HOURS)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONERROR,
|
|
IDS_LOGONTITLE,
|
|
IDS_INVALIDLOGONHOURS);
|
|
goto done;
|
|
}
|
|
else if (SubStatus == STATUS_INVALID_WORKSTATION)
|
|
{
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONERROR,
|
|
IDS_LOGONTITLE,
|
|
IDS_INVALIDWORKSTATION);
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
TRACE("Other error!\n");
|
|
ResourceMessageBox(pgContext,
|
|
hwndDlg,
|
|
MB_OK | MB_ICONERROR,
|
|
IDS_LOGONTITLE,
|
|
IDS_ACCOUNTRESTRICTION);
|
|
goto done;
|
|
}
|
|
}
|
|
else if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("DoLoginTasks failed! Status 0x%08lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
if (!CreateProfile(pgContext, UserName, Domain, Password))
|
|
{
|
|
ERR("Failed to create the profile!\n");
|
|
goto done;
|
|
}
|
|
|
|
ZeroMemory(pgContext->Password, sizeof(pgContext->Password));
|
|
wcscpy(pgContext->Password, Password);
|
|
|
|
result = TRUE;
|
|
|
|
done:
|
|
pgContext->bAutoAdminLogon = FALSE;
|
|
|
|
if (UserName != NULL)
|
|
HeapFree(GetProcessHeap(), 0, UserName);
|
|
|
|
if (Password != NULL)
|
|
HeapFree(GetProcessHeap(), 0, Password);
|
|
|
|
if (Domain != NULL)
|
|
HeapFree(GetProcessHeap(), 0, Domain);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static
|
|
VOID
|
|
SetDomainComboBox(
|
|
HWND hwndDomainComboBox,
|
|
PGINA_CONTEXT pgContext)
|
|
{
|
|
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD dwComputerNameLength;
|
|
LONG lIndex = 0;
|
|
LONG lFindIndex;
|
|
|
|
SendMessageW(hwndDomainComboBox, CB_RESETCONTENT, 0, 0);
|
|
|
|
dwComputerNameLength = _countof(szComputerName);
|
|
if (GetComputerNameW(szComputerName, &dwComputerNameLength))
|
|
{
|
|
lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)szComputerName);
|
|
}
|
|
|
|
if (wcslen(pgContext->DomainName) != 0)
|
|
{
|
|
lFindIndex = SendMessageW(hwndDomainComboBox, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pgContext->DomainName);
|
|
if (lFindIndex == CB_ERR)
|
|
{
|
|
lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)pgContext->DomainName);
|
|
}
|
|
else
|
|
{
|
|
lIndex = lFindIndex;
|
|
}
|
|
}
|
|
|
|
SendMessageW(hwndDomainComboBox, CB_SETCURSEL, lIndex, 0);
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
LogonDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PDLG_DATA pDlgData;
|
|
|
|
pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
/* FIXME: take care of NoDomainUI */
|
|
pDlgData = DlgData_Create(hwndDlg, (PGINA_CONTEXT)lParam);
|
|
if (pDlgData == NULL)
|
|
return FALSE;
|
|
|
|
DlgData_LoadBitmaps(pDlgData);
|
|
|
|
SetWelcomeText(hwndDlg);
|
|
|
|
if (pDlgData->pgContext->bAutoAdminLogon ||
|
|
!pDlgData->pgContext->bDontDisplayLastUserName)
|
|
SetDlgItemTextW(hwndDlg, IDC_LOGON_USERNAME, pDlgData->pgContext->UserName);
|
|
|
|
if (pDlgData->pgContext->bAutoAdminLogon)
|
|
SetDlgItemTextW(hwndDlg, IDC_LOGON_PASSWORD, pDlgData->pgContext->Password);
|
|
|
|
SetDomainComboBox(GetDlgItem(hwndDlg, IDC_LOGON_DOMAIN), pDlgData->pgContext);
|
|
|
|
if (pDlgData->pgContext->bDisableCAD)
|
|
EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
|
|
|
|
if (!pDlgData->pgContext->bShutdownWithoutLogon)
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_LOGON_SHUTDOWN), FALSE);
|
|
|
|
SetFocus(GetDlgItem(hwndDlg, pDlgData->pgContext->bDontDisplayLastUserName ? IDC_LOGON_USERNAME : IDC_LOGON_PASSWORD));
|
|
|
|
if (pDlgData->pgContext->bAutoAdminLogon)
|
|
PostMessage(GetDlgItem(hwndDlg, IDOK), BM_CLICK, 0, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
if (pDlgData && pDlgData->hLogoBitmap)
|
|
{
|
|
BeginPaint(hwndDlg, &ps);
|
|
DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hLogoBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
|
|
EndPaint(hwndDlg, &ps);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
DlgData_Destroy(pDlgData);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
if (DoLogon(hwndDlg, pDlgData->pgContext))
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_LOGON);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
|
|
return TRUE;
|
|
|
|
case IDC_LOGON_SHUTDOWN:
|
|
if (OnShutDown(hwndDlg, pDlgData->pgContext) == IDOK)
|
|
EndDialog(hwndDlg, pDlgData->pgContext->nShutdownAction);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static
|
|
INT_PTR
|
|
CALLBACK
|
|
LegalNoticeDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PLEGALNOTICEDATA pLegalNotice;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pLegalNotice = (PLEGALNOTICEDATA)lParam;
|
|
SetWindowTextW(hwndDlg, pLegalNotice->pszCaption);
|
|
SetDlgItemTextW(hwndDlg, IDC_LEGALNOTICE_TEXT, pLegalNotice->pszText);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
EndDialog(hwndDlg, 0);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, 0);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static INT
|
|
GUILoggedOutSAS(
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
LEGALNOTICEDATA LegalNotice = {NULL, NULL};
|
|
HKEY hKey = NULL;
|
|
LONG rc;
|
|
int result;
|
|
|
|
TRACE("GUILoggedOutSAS()\n");
|
|
|
|
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKey);
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
ReadRegSzValue(hKey,
|
|
L"LegalNoticeCaption",
|
|
&LegalNotice.pszCaption);
|
|
|
|
ReadRegSzValue(hKey,
|
|
L"LegalNoticeText",
|
|
&LegalNotice.pszText);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (LegalNotice.pszCaption != NULL && wcslen(LegalNotice.pszCaption) != 0 &&
|
|
LegalNotice.pszText != NULL && wcslen(LegalNotice.pszText) != 0)
|
|
{
|
|
pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_LEGALNOTICE),
|
|
GetDesktopWindow(),
|
|
LegalNoticeDialogProc,
|
|
(LPARAM)&LegalNotice);
|
|
}
|
|
|
|
if (LegalNotice.pszCaption != NULL)
|
|
HeapFree(GetProcessHeap(), 0, LegalNotice.pszCaption);
|
|
|
|
if (LegalNotice.pszText != NULL)
|
|
HeapFree(GetProcessHeap(), 0, LegalNotice.pszText);
|
|
|
|
result = pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_LOGON),
|
|
GetDesktopWindow(),
|
|
LogonDialogProc,
|
|
(LPARAM)pgContext);
|
|
if (result >= WLX_SAS_ACTION_LOGON &&
|
|
result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
|
|
{
|
|
WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
|
|
return result;
|
|
}
|
|
|
|
WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
|
|
return WLX_SAS_ACTION_NONE;
|
|
}
|
|
|
|
|
|
static VOID
|
|
SetLockMessage(HWND hwnd,
|
|
INT nDlgItem,
|
|
PGINA_CONTEXT pgContext)
|
|
{
|
|
WCHAR Buffer1[256];
|
|
WCHAR Buffer2[256];
|
|
WCHAR Buffer3[512];
|
|
|
|
LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, _countof(Buffer1));
|
|
|
|
wsprintfW(Buffer2, L"%s\\%s", pgContext->DomainName, pgContext->UserName);
|
|
wsprintfW(Buffer3, Buffer1, Buffer2);
|
|
|
|
SetDlgItemTextW(hwnd, nDlgItem, Buffer3);
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
DoUnlock(
|
|
IN HWND hwndDlg,
|
|
IN PGINA_CONTEXT pgContext,
|
|
OUT LPINT Action)
|
|
{
|
|
WCHAR Buffer1[256];
|
|
WCHAR Buffer2[256];
|
|
LPWSTR UserName = NULL;
|
|
LPWSTR Password = NULL;
|
|
BOOL res = FALSE;
|
|
|
|
if (GetTextboxText(hwndDlg, IDC_UNLOCK_USERNAME, &UserName) && *UserName == '\0')
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, UserName);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetTextboxText(hwndDlg, IDC_UNLOCK_PASSWORD, &Password))
|
|
{
|
|
if (UserName != NULL && Password != NULL &&
|
|
wcscmp(UserName, pgContext->UserName) == 0 &&
|
|
wcscmp(Password, pgContext->Password) == 0)
|
|
{
|
|
*Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
|
|
res = TRUE;
|
|
}
|
|
else if (wcscmp(UserName, pgContext->UserName) == 0 &&
|
|
wcscmp(Password, pgContext->Password) != 0)
|
|
{
|
|
/* Wrong Password */
|
|
LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGPASSWORD, Buffer2, _countof(Buffer2));
|
|
LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
|
|
MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
|
|
}
|
|
else
|
|
{
|
|
/* Wrong user name */
|
|
if (DoAdminUnlock(pgContext, UserName, NULL, Password))
|
|
{
|
|
*Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
|
|
res = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGUSER, Buffer1, _countof(Buffer1));
|
|
wsprintfW(Buffer2, Buffer1, pgContext->DomainName, pgContext->UserName);
|
|
LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
|
|
MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (UserName != NULL)
|
|
HeapFree(GetProcessHeap(), 0, UserName);
|
|
|
|
if (Password != NULL)
|
|
HeapFree(GetProcessHeap(), 0, Password);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
static
|
|
INT_PTR
|
|
CALLBACK
|
|
UnlockDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PDLG_DATA pDlgData;
|
|
INT result = WLX_SAS_ACTION_NONE;
|
|
|
|
pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pDlgData = DlgData_Create(hwndDlg, (PGINA_CONTEXT)lParam);
|
|
if (pDlgData == NULL)
|
|
return FALSE;
|
|
|
|
SetWelcomeText(hwndDlg);
|
|
|
|
SetLockMessage(hwndDlg, IDC_UNLOCK_MESSAGE, pDlgData->pgContext);
|
|
|
|
SetDlgItemTextW(hwndDlg, IDC_UNLOCK_USERNAME, pDlgData->pgContext->UserName);
|
|
SetFocus(GetDlgItem(hwndDlg, IDC_UNLOCK_PASSWORD));
|
|
|
|
if (pDlgData->pgContext->bDisableCAD)
|
|
EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
|
|
|
|
DlgData_LoadBitmaps(pDlgData);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
if (pDlgData && pDlgData->hLogoBitmap)
|
|
{
|
|
BeginPaint(hwndDlg, &ps);
|
|
DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hLogoBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
|
|
EndPaint(hwndDlg, &ps);
|
|
}
|
|
return TRUE;
|
|
}
|
|
case WM_DESTROY:
|
|
DlgData_Destroy(pDlgData);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
if (DoUnlock(hwndDlg, pDlgData->pgContext, &result))
|
|
EndDialog(hwndDlg, result);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static INT
|
|
GUILockedSAS(
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
int result;
|
|
|
|
TRACE("GUILockedSAS()\n");
|
|
|
|
result = pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_UNLOCK),
|
|
GetDesktopWindow(),
|
|
UnlockDialogProc,
|
|
(LPARAM)pgContext);
|
|
if (result >= WLX_SAS_ACTION_LOGON &&
|
|
result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
|
|
{
|
|
WARN("GUILockedSAS() returns 0x%x\n", result);
|
|
return result;
|
|
}
|
|
|
|
WARN("GUILockedSAS() failed (0x%x)\n", result);
|
|
return WLX_SAS_ACTION_NONE;
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK
|
|
LockedDialogProc(
|
|
IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PDLG_DATA pDlgData;
|
|
|
|
pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pDlgData = DlgData_Create(hwndDlg, (PGINA_CONTEXT)lParam);
|
|
if (pDlgData == NULL)
|
|
return FALSE;
|
|
|
|
DlgData_LoadBitmaps(pDlgData);
|
|
|
|
SetWelcomeText(hwndDlg);
|
|
|
|
SetLockMessage(hwndDlg, IDC_LOCKED_MESSAGE, pDlgData->pgContext);
|
|
return TRUE;
|
|
}
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
if (pDlgData && pDlgData->hLogoBitmap)
|
|
{
|
|
BeginPaint(hwndDlg, &ps);
|
|
DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hLogoBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
|
|
EndPaint(hwndDlg, &ps);
|
|
}
|
|
return TRUE;
|
|
}
|
|
case WM_DESTROY:
|
|
{
|
|
DlgData_Destroy(pDlgData);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static VOID
|
|
GUIDisplayLockedNotice(
|
|
IN OUT PGINA_CONTEXT pgContext)
|
|
{
|
|
TRACE("GUIdisplayLockedNotice()\n");
|
|
|
|
pgContext->pWlxFuncs->WlxDialogBoxParam(
|
|
pgContext->hWlx,
|
|
pgContext->hDllInstance,
|
|
MAKEINTRESOURCEW(IDD_LOCKED),
|
|
GetDesktopWindow(),
|
|
LockedDialogProc,
|
|
(LPARAM)pgContext);
|
|
}
|
|
|
|
GINA_UI GinaGraphicalUI = {
|
|
GUIInitialize,
|
|
GUIDisplayStatusMessage,
|
|
GUIRemoveStatusMessage,
|
|
GUIDisplaySASNotice,
|
|
GUILoggedOnSAS,
|
|
GUILoggedOutSAS,
|
|
GUILockedSAS,
|
|
GUIDisplayLockedNotice,
|
|
};
|