mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
61c8d3432c
The ReactOS logo banner is loaded from the GINA context whereas the animation bar is loaded from the main application instance. However, the aforementioned context is not initialized when WM_INITDIALOG occurs hence DlgData_LoadBitmaps() would fail on proceeding at loading the remaining bitmaps to be loaded.
This fixes the regression introduced by commit 623dd26c
(PR #2353).
1595 lines
44 KiB
C
1595 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;
|
|
|
|
typedef struct _DLG_DATA
|
|
{
|
|
PGINA_CONTEXT pgContext;
|
|
HBITMAP hLogoBitmap;
|
|
HBITMAP hBarBitmap;
|
|
UINT_PTR TimerID;
|
|
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))
|
|
{
|
|
pDlgData->TimerID = SetTimer(hwndDlg, -1, 20, NULL);
|
|
}
|
|
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(hwndDlg, NULL, FALSE);
|
|
UpdateWindow(hwndDlg);
|
|
}
|
|
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, pDlgData->TimerID);
|
|
}
|
|
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,
|
|
};
|