2020-09-30 17:12:29 +02:00

1263 lines
38 KiB
C

/****************************** Module Header ******************************\
* Module Name: chngpwd.c
*
* Copyright (c) 1991, Microsoft Corporation
*
* Implementation of change-password functionality of winlogon
*
* History:
* 12-09-91 Davidc Created.
\***************************************************************************/
#include "msgina.h"
#include <stdio.h>
#include <wchar.h>
// #define VERBOSE_UTILS
#ifdef VERBOSE_UTILS
#define VerbosePrint(s) WLPrint(s)
#else
#define VerbosePrint(s)
#endif
//
// Define the structure used to pass data into the change password dialog
//
typedef struct _MPR_DATA {
struct _MPR_DATA * Next;
PWSTR pszProviderName;
} MPR_DATA, * PMPR_DATA;
typedef struct {
PGLOBALS pGlobals;
PWCHAR UserName;
PWCHAR Domain;
PWCHAR OldPassword;
BOOL AnyDomain;
BOOL Impersonate;
BOOL AllowProviderOnly;
PMPR_DATA MprList;
} CHANGE_PASSWORD_DATA;
typedef CHANGE_PASSWORD_DATA *PCHANGE_PASSWORD_DATA;
//
// Private prototypes
//
BOOL WINAPI ChangePasswordDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL ChangePasswordDlgInit(HWND, LONG);
DLG_RETURN_TYPE AttemptPasswordChange(HWND);
DLG_RETURN_TYPE
HandleFailedChangePassword(
HWND hDlg,
NTSTATUS Status,
PWCHAR UserName,
PWCHAR Domain,
PMSV1_0_CHANGEPASSWORD_RESPONSE pChangePasswordResponse
);
BOOL WINAPI
ChangePasswordHelpDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
);
/***************************************************************************\
* FUNCTION: ChangePassword
*
* PURPOSE: Attempts to change a user's password
*
* ARGUMENTS:
*
* hwnd - the most recent parent window
* pGlobals - pointer to global data for this instance.
* The password information of this data will be
* updated upon successful change of the primary
* authenticator's password information.
* UserName - the name of the user to change
* Domain - the domain name to change the password on
* AnyDomain - if TRUE the user may select any trusted domain, or
* enter the name of any other domain
*
* RETURNS:
*
* MSGINA_DLG_SUCCESS - the password was changed successfully.
* MSGINA_DLG_FAILURE - the user's password could not be changed.
* DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
*
* HISTORY:
*
* 12-09-91 Davidc Created.
*
\***************************************************************************/
DLG_RETURN_TYPE
ChangePassword(
HWND hwnd,
PGLOBALS pGlobals,
PWCHAR UserName,
PWCHAR Domain,
BOOL AnyDomain)
{
CHANGE_PASSWORD_DATA PasswordData;
DLG_RETURN_TYPE Result;
HWND hwndOldFocus = GetFocus();
PasswordData.pGlobals = pGlobals;
PasswordData.UserName = UserName;
PasswordData.Domain = Domain;
PasswordData.OldPassword = NULL;
PasswordData.AnyDomain = AnyDomain;
PasswordData.Impersonate = TRUE;
PasswordData.AllowProviderOnly = TRUE;
PasswordData.MprList = NULL;
pWlxFuncs->WlxSetTimeout(hGlobalWlx, LOGON_TIMEOUT);
Result = pWlxFuncs->WlxDialogBoxParam( hGlobalWlx,
hDllInstance,
MAKEINTRESOURCE(IDD_CHANGEPWD_DIALOG),
hwnd,
ChangePasswordDlgProc,
(LONG)&PasswordData);
SetFocus(hwndOldFocus);
return(Result);
}
/***************************************************************************\
* FUNCTION: ChangePasswordLogon
*
* PURPOSE: Attempts to change a user's password during the logon process.
* This is the same as a normal change password except that the user
* does not have to enter the old password and can only change the
* password in the specified domain. This routine is intended to be
* called during logon when it is discovered that the user's
* password has expired.
*
* ARGUMENTS:
*
* hwnd - the most recent parent window
* pGlobals - pointer to global data for this instance
* UserName - the name of the user to change
* Domain - the domain name to change the password on
* OldPassword - the old user password
* NewPassword - points to a buffer that the new password is written
* into if the password is changed successfully.
* NewPasswordMaxBytes - the size of the newpassword buffer.
*
* RETURNS:
*
* MSGINA_DLG_SUCCESS - the password was changed successfully, NewPassword
* contains the new password text.
* MSGINA_DLG_FAILURE - the user's password could not be changed.
* DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
*
* HISTORY:
*
* 12-09-91 Davidc Created.
*
\***************************************************************************/
DLG_RETURN_TYPE
ChangePasswordLogon(
HWND hwnd,
PGLOBALS pGlobals,
PWCHAR UserName,
PWCHAR Domain,
PWCHAR OldPassword
)
{
CHANGE_PASSWORD_DATA PasswordData;
DLG_RETURN_TYPE Result;
PasswordData.pGlobals = pGlobals;
PasswordData.UserName = UserName;
PasswordData.Domain = Domain;
PasswordData.OldPassword = OldPassword;
PasswordData.AnyDomain = FALSE;
PasswordData.Impersonate = FALSE;
PasswordData.AllowProviderOnly = FALSE;
PasswordData.MprList = NULL;
pWlxFuncs->WlxSetTimeout(hGlobalWlx, LOGON_TIMEOUT);
Result = pWlxFuncs->WlxDialogBoxParam( hGlobalWlx,
hDllInstance,
MAKEINTRESOURCE( IDD_CHANGEPWD_DIALOG ),
hwnd,
ChangePasswordDlgProc,
(LONG)&PasswordData);
return(Result);
}
/****************************************************************************\
*
* FUNCTION: ChangePasswordDlgProc
*
* PURPOSE: Processes messages for ChangePassword dialog
*
* HISTORY:
*
* 12-09-91 Davidc Created.
*
\****************************************************************************/
BOOL WINAPI ChangePasswordDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
PCHANGE_PASSWORD_DATA pPasswordData = (PCHANGE_PASSWORD_DATA)GetWindowLong(hDlg, GWL_USERDATA);
PGLOBALS pGlobals;
DLG_RETURN_TYPE Result;
int Index;
PMPR_DATA pData;
LONG ProviderKey;
switch (message) {
case WM_INITDIALOG:
{
if (!ChangePasswordDlgInit(hDlg, lParam)) {
EndDialog(hDlg, MSGINA_DLG_FAILURE);
}
return(SetPasswordFocus(hDlg));
}
case WM_CLOSE:
while (pPasswordData->MprList)
{
pData = pPasswordData->MprList;
pPasswordData->MprList = pData->Next;
LocalFree( pData );
}
return( TRUE );
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case ID_NEXT:
{
}
case IDOK:
{
pGlobals=pPasswordData->pGlobals;
//
// Deal with combo-box UI requirements
//
if (HandleComboBoxOK(hDlg, IDD_CHANGEPWD_DOMAIN)) {
return(TRUE);
}
Index = SendMessage( GetDlgItem( hDlg, IDD_CHANGEPWD_DOMAIN ),
CB_GETCURSEL,
0, 0 );
if ( Index != -1 )
{
pData = (PMPR_DATA) SendMessage(
GetDlgItem( hDlg, IDD_CHANGEPWD_DOMAIN),
CB_GETITEMDATA,
Index, 0 );
}
else
{
pData = NULL;
}
if ( pData )
{
HWND hwndOwner;
WCHAR TempBuf[MAX_STRING_BYTES];
TCHAR UserName[MAX_STRING_BYTES];
TCHAR Domain[MAX_STRING_BYTES];
TCHAR Password[MAX_STRING_BYTES];
TCHAR NewPassword[MAX_STRING_BYTES];
TCHAR ConfirmNewPassword[MAX_STRING_BYTES];
WLX_MPR_NOTIFY_INFO MprInfo;
GetDlgItemText(hDlg, IDD_CHANGEPWD_NAME, TempBuf, MAX_STRING_BYTES);
MprInfo.pszUserName = DupString(TempBuf);
GetDlgItemText(hDlg, IDD_CHANGEPWD_DOMAIN, TempBuf, MAX_STRING_BYTES);
MprInfo.pszDomain = DupString(TempBuf);
GetDlgItemText(hDlg, IDD_CHANGEPWD_OLD, TempBuf, MAX_STRING_BYTES);
MprInfo.pszOldPassword = DupString(TempBuf);
GetDlgItemText(hDlg, IDD_CHANGEPWD_NEW, TempBuf, MAX_STRING_BYTES);
MprInfo.pszPassword = DupString(TempBuf);
//
// Hide this dialog and pass our parent as the owner
// of any provider dialogs
//
ShowWindow(hDlg, SW_HIDE);
hwndOwner = GetParent(hDlg);
Result = pWlxFuncs->WlxChangePasswordNotifyEx(
hGlobalWlx,
&MprInfo,
0,
pData->pszProviderName,
NULL );
EndDialog(hDlg, MSGINA_DLG_SUCCESS );
return(TRUE);
}
Result = AttemptPasswordChange(hDlg);
if (Result == MSGINA_DLG_FAILURE) {
//
// Let the user try again
// We always make the user re-enter at least the new password.
//
SetDlgItemText(hDlg, IDD_CHANGEPWD_NEW, NULL);
SetDlgItemText(hDlg, IDD_CHANGEPWD_CONFIRM, NULL);
SetPasswordFocus(hDlg);
//EndDialog(hDlg, Result);
return(TRUE);
}
//
// We're finished - either success or an interrupt
//
if (DLG_SUCCEEDED( Result )) {
LPTSTR NewUserName;
LPTSTR NewDomain;
//
// Return the new password to the caller if the password
// was changed on the account they passed in. Be sure to
// hide it so that it isn't recognizable in pagefiles.
//
NewUserName = AllocAndGetDlgItemText(hDlg, IDD_CHANGEPWD_NAME);
if (NewUserName != NULL) {
if (lstrcmp(NewUserName, pPasswordData->UserName) == 0) {
NewDomain = AllocAndGetDlgItemText(hDlg, IDD_CHANGEPWD_DOMAIN);
if (NewDomain != NULL) {
if (lstrcmp(NewDomain, pPasswordData->Domain) == 0) {
//
// Return the new password to the caller
//
GetDlgItemText(hDlg,
IDD_CHANGEPWD_NEW,
pGlobals->Password,
sizeof(pGlobals->Password));
//
// Hide the password.
// Use the existing seed.
//
RtlInitUnicodeString(
&pGlobals->PasswordString,
pGlobals->Password);
HidePassword(
&pGlobals->Seed,
&pGlobals->PasswordString);
}
Free(NewDomain);
}
}
Free(NewUserName);
}
}
EndDialog(hDlg, Result);
return(TRUE);
}
case IDCANCEL:
{
EndDialog(hDlg, MSGINA_DLG_FAILURE);
return(TRUE);
}
case IDD_CHANGEPWD_HELP:
{
LPTSTR Id;
PGLOBALS pGlobals = pPasswordData->pGlobals;
if (GetWindowLong(GetDlgItem(hDlg, IDD_CHANGEPWD_OLD), GWL_STYLE) & WS_VISIBLE) {
Id = (LPTSTR) IDD_CHANGE_PASSWORD_HELP;
} else {
Id = (LPTSTR) IDD_CHANGE_PASSWORD_EXPIRED_HELP;
}
Result = pWlxFuncs->WlxDialogBoxParam( hGlobalWlx,
hDllInstance,
Id,
hDlg,
ChangePasswordHelpDlgProc,
(LONG)pGlobals);
if ( Result != MSGINA_DLG_SUCCESS )
{
EndDialog( hDlg, SetInterruptFlag( MSGINA_DLG_FAILURE ) );
}
return(TRUE);
}
}
break;
}
case WLX_WM_SAS:
{
// Ignore it
return(TRUE);
}
}
// We didn't process this message
return FALSE;
}
VOID
AddNetworkProviders(
CHANGE_PASSWORD_DATA * pData,
HWND hDlg,
UINT Id)
{
WCHAR szProviderName[128];
WCHAR szKeyPath[MAX_PATH];
PWSTR pszProviders;
PWSTR pszScan;
PWSTR pszStart;
WCHAR Save;
HKEY hKey;
DWORD dwType;
DWORD dwLen;
DWORD Class;
int err;
HWND hCB;
int Index;
PMPR_DATA pMprData;
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"),
0,
KEY_READ,
&hKey );
if ( err )
{
return;
}
err = RegQueryValueEx( hKey,
TEXT("ProviderOrder"),
NULL,
&dwType,
NULL,
&dwLen );
if ( (err) || (dwType != REG_SZ) )
{
RegCloseKey( hKey );
return;
}
pszProviders = LocalAlloc( LMEM_FIXED, dwLen );
if ( !pszProviders )
{
RegCloseKey( hKey );
return;
}
err = RegQueryValueEx( hKey,
TEXT("ProviderOrder"),
NULL,
&dwType,
(PUCHAR) pszProviders,
&dwLen );
RegCloseKey( hKey );
if ( err )
{
LocalFree( pszProviders );
return;
}
//
// Initialize things.
//
pszStart = pszProviders;
hCB = GetDlgItem( hDlg, Id );
szProviderName[0] = TEXT('<');
szProviderName[1] = TEXT(' ');
while ( *pszStart )
{
pszScan = pszStart;
while ( (*pszScan) && (*pszScan != TEXT(',') ) )
{
pszScan++;
}
Save = *pszScan;
*pszScan = TEXT('\0');
wsprintf( szKeyPath,
TEXT("System\\CurrentControlSet\\Services\\%s\\networkprovider"),
pszStart );
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szKeyPath,
0,
KEY_READ,
&hKey );
if ( err == 0 )
{
dwLen = sizeof(DWORD) ;
err = RegQueryValueEx( hKey,
TEXT("Class"),
NULL,
&dwType,
(PUCHAR) &Class,
&dwLen );
if ( (err == 0) && (dwType == REG_DWORD) )
{
if ( Class & WN_CREDENTIAL_CLASS )
{
pMprData = LocalAlloc( LMEM_FIXED,
sizeof(MPR_DATA) +
(wcslen( pszStart ) + 1) * sizeof(WCHAR) );
if (pMprData)
{
pMprData->pszProviderName = (PWSTR) (pMprData + 1);
wcscpy( pMprData->pszProviderName, pszStart );
pMprData->Next = pData->MprList;
pData->MprList = pMprData;
dwLen = 126 * sizeof(WCHAR);
err = RegQueryValueEx( hKey,
TEXT("Name"),
NULL,
&dwType,
(PUCHAR) &szProviderName[2],
&dwLen );
wcscpy( &szProviderName[ (dwLen / sizeof(WCHAR) ) + 2 ],
TEXT(" >") );
Index = SendMessage( hCB,
CB_ADDSTRING,
0,
(LONG) szProviderName );
SendMessage( hCB, CB_SETITEMDATA, Index, (LONG) pMprData );
}
}
}
RegCloseKey( hKey );
}
*pszScan = Save;
if ( *pszScan )
{
pszStart = pszScan + 1;
}
else
{
pszStart = NULL;
break;
}
}
LocalFree( pszProviders );
}
/****************************************************************************\
*
* FUNCTION: ChangePasswordDlgInit
*
* PURPOSE: Handles initialization of change password dialog
*
* RETURNS: TRUE on success, FALSE on failure
*
* HISTORY:
*
* 12-09-91 Davidc Created.
*
\****************************************************************************/
BOOL
ChangePasswordDlgInit(
HWND hDlg,
LONG lParam
)
{
PCHANGE_PASSWORD_DATA pPasswordData = (PCHANGE_PASSWORD_DATA)lParam;
PGLOBALS pGlobals = pPasswordData->pGlobals;
DLG_RETURN_TYPE Result;
// Store our structure pointer
SetWindowLong(hDlg, GWL_USERDATA, lParam);
// Set up the initial text field contents
SetDlgItemText(hDlg, IDD_CHANGEPWD_NAME, pPasswordData->UserName);
SetDlgItemText(hDlg, IDD_CHANGEPWD_OLD, pPasswordData->OldPassword);
// If the user can choose their domain, fill the domain combobox
// with the known domains and the local machine name. Otherwise
// disable the domain combobox.
if (pPasswordData->AnyDomain) {
Result = FillTrustedDomainCB(pGlobals, hDlg, IDD_CHANGEPWD_DOMAIN,
pPasswordData->Domain, TRUE);
if (DLG_INTERRUPTED(Result)) {
EndDialog(hDlg, Result);
}
if ( pPasswordData->AllowProviderOnly )
{
AddNetworkProviders( pPasswordData, hDlg, IDD_CHANGEPWD_DOMAIN );
}
} else {
SendDlgItemMessage(hDlg, IDD_CHANGEPWD_DOMAIN, CB_ADDSTRING, 0, (LONG)pPasswordData->Domain);
SendDlgItemMessage(hDlg, IDD_CHANGEPWD_DOMAIN, CB_SETCURSEL, 0, 0);
EnableWindow(GetDlgItem(hDlg, IDD_CHANGEPWD_DOMAIN), FALSE);
}
CentreWindow(hDlg);
SetupSystemMenu(hDlg);
return TRUE;
}
/****************************************************************************\
*
* FUNCTION: AttemptPasswordChange
*
* PURPOSE: Tries to change the user's password using the current values in
* the change-password dialog controls
*
* RETURNS: MSGINA_DLG_SUCCESS if the password was changed successfully.
* MSGINA_DLG_FAILURE if the change failed
* DLG_INTERRUPTED() - this is a set of possible interruptions (see winlogon.h)
*
* NOTES: If the password change failed, this routine displays the necessary
* dialogs explaining what failed and why before returning.
* This routine also clears the fields that need re-entry before
* returning so the calling routine can call SetPasswordFocus on
* the dialog to put the focus in the appropriate place.
*
* HISTORY:
*
* 12-09-91 Davidc Created.
*
\****************************************************************************/
DLG_RETURN_TYPE
AttemptPasswordChange(
HWND hDlg
)
{
PCHANGE_PASSWORD_DATA pPasswordData = (PCHANGE_PASSWORD_DATA)GetWindowLong(hDlg, GWL_USERDATA);
PGLOBALS pGlobals = pPasswordData->pGlobals;
TCHAR UserName[MAX_STRING_BYTES];
TCHAR Domain[MAX_STRING_BYTES];
TCHAR Password[MAX_STRING_BYTES];
TCHAR NewPassword[MAX_STRING_BYTES];
TCHAR ConfirmNewPassword[MAX_STRING_BYTES];
DLG_RETURN_TYPE Result;
DLG_RETURN_TYPE ReturnResult = MSGINA_DLG_SUCCESS;
NTSTATUS Status;
NTSTATUS ProtocolStatus;
PMSV1_0_CHANGEPASSWORD_REQUEST pChangePasswordRequest = NULL;
PMSV1_0_CHANGEPASSWORD_RESPONSE pChangePasswordResponse;
PWCHAR DomainU;
PWCHAR UserNameU;
PWCHAR PasswordU;
PWCHAR NewPasswordU;
int Length;
ULONG RequestBufferSize;
ULONG ResponseBufferSize;
DWORD ChangeInfo = 0;
HWND hwndOwner;
HANDLE ImpersonationHandle;
WLX_MPR_NOTIFY_INFO MprInfo;
UCHAR Seed = 0;
PSECURITY_SEED_AND_LENGTH SeedAndLength;
int MprResult;
GetDlgItemText(hDlg, IDD_CHANGEPWD_NAME, UserName, MAX_STRING_BYTES);
GetDlgItemText(hDlg, IDD_CHANGEPWD_DOMAIN, Domain, MAX_STRING_BYTES);
GetDlgItemText(hDlg, IDD_CHANGEPWD_OLD, Password, MAX_STRING_BYTES);
GetDlgItemText(hDlg, IDD_CHANGEPWD_NEW, NewPassword, MAX_STRING_BYTES);
GetDlgItemText(hDlg, IDD_CHANGEPWD_CONFIRM, ConfirmNewPassword, MAX_STRING_BYTES);
//
// Check that new passwords match
//
if (lstrcmp(NewPassword, ConfirmNewPassword) != 0) {
Result = TimeoutMessageBox(hDlg, IDS_NO_PASSWORD_CONFIRM,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
if (DLG_INTERRUPTED(Result)) {
Result = SetInterruptFlag( MSGINA_DLG_FAILURE );
}
else
{
Result = MSGINA_DLG_FAILURE ;
}
return(Result);
}
//
// Determine request buffer size needed, including room for
// strings. Set string pointers to offsets as we step through
// sizing each one.
//
RequestBufferSize = sizeof(*pChangePasswordRequest);
UserNameU = (PVOID)RequestBufferSize;
RequestBufferSize += (lstrlen(UserName)+1) * sizeof(WCHAR);
DomainU = (PVOID)RequestBufferSize;
RequestBufferSize += (lstrlen(Domain)+1) * sizeof(WCHAR);
PasswordU = (PVOID)RequestBufferSize;
RequestBufferSize += (lstrlen(Password)+1) * sizeof(WCHAR);
NewPasswordU = (PVOID)RequestBufferSize;
RequestBufferSize += (lstrlen(NewPassword)+1) * sizeof(WCHAR);
//
// Allocate request buffer
//
pChangePasswordRequest = Alloc(RequestBufferSize);
if (NULL == pChangePasswordRequest) {
DebugLog((DEB_ERROR, "cannot allocate change password request buffer (%ld bytes).", RequestBufferSize));
return MSGINA_DLG_FAILURE;
}
//
// Fixup string offsets to string pointers for request.
//
UserNameU = (PVOID) ((PBYTE)pChangePasswordRequest + (ULONG)UserNameU);
DomainU = (PVOID) ((PBYTE)pChangePasswordRequest + (ULONG)DomainU);
PasswordU = (PVOID) ((PBYTE)pChangePasswordRequest + (ULONG)PasswordU);
NewPasswordU = (PVOID) ((PBYTE)pChangePasswordRequest + (ULONG)NewPasswordU);
//
// Setup MSV1_0ChangePassword request.
//
pChangePasswordRequest->MessageType = MsV1_0ChangePassword;
// strings are already unicode, just copy them // lhb tracks //REVIEW
lstrcpy((LPTSTR)UserNameU,UserName);
lstrcpy((LPTSTR)DomainU,Domain);
lstrcpy((LPTSTR)PasswordU,Password);
lstrcpy((LPTSTR)NewPasswordU,NewPassword);
Length = lstrlen(UserName);
UserNameU[Length] = 0;
RtlInitUnicodeString(
&pChangePasswordRequest->AccountName,
UserNameU
);
Length = lstrlen(Domain);
DomainU[Length] = 0;
RtlInitUnicodeString(
&pChangePasswordRequest->DomainName,
DomainU
);
Length = lstrlen(Password);
PasswordU[Length] = 0;
RtlInitUnicodeString(
&pChangePasswordRequest->OldPassword,
PasswordU
);
Length = lstrlen(NewPassword);
NewPasswordU[Length] = 0;
RtlInitUnicodeString(
&pChangePasswordRequest->NewPassword,
NewPasswordU
);
//
// Make sure the passwords are short enough that we can run-encode them.
//
if ((pChangePasswordRequest->OldPassword.Length > 127) ||
(pChangePasswordRequest->NewPassword.Length > 127)) {
Status = STATUS_ILL_FORMED_PASSWORD;
} else {
HidePassword(NULL,&pChangePasswordRequest->OldPassword);
HidePassword(NULL,&pChangePasswordRequest->NewPassword);
Status = STATUS_SUCCESS ;
}
//
// If that succeeded, try to change the password
//
if (NT_SUCCESS(Status)) {
//
// This could take some time, put up a wait cursor
//
SetupCursor(TRUE);
//
// We want to impersonate if and only if the user is actually logged
// on. Otherwise we'll be impersonating SYSTEM, which is bad.
//
if (pPasswordData->Impersonate) {
ImpersonationHandle = ImpersonateUser(
&pGlobals->UserProcessData,
NULL
);
if (NULL == ImpersonationHandle) {
DebugLog((DEB_ERROR, "cannot impersonate user"));
Free(pChangePasswordRequest);
return MSGINA_DLG_FAILURE;
}
}
//
// Tell msv1_0 whether or not we're impersonating.
//
pChangePasswordRequest->Impersonating = pPasswordData->Impersonate;
//
// Call off to the authentication package to do the work
//
Status = LsaCallAuthenticationPackage(
pGlobals->LsaHandle,
pGlobals->AuthenticationPackage,
pChangePasswordRequest,
RequestBufferSize,
(PVOID)&pChangePasswordResponse,
&ResponseBufferSize,
&ProtocolStatus
);
if (pPasswordData->Impersonate) {
if (!StopImpersonating(ImpersonationHandle)) {
DebugLog((DEB_ERROR, "AttemptPasswordChange: Failed to revert to self"));
//
// Blow up
//
ASSERT(FALSE);
}
}
//
// Restore the normal cursor
//
SetupCursor(FALSE);
}
//
// Free up the request buffer
//
Free(pChangePasswordRequest);
//
// Get the most informative status code
//
if ( NT_SUCCESS(Status) ) {
Status = ProtocolStatus;
}
else
{
DebugLog((DEB_TRACE, "FAILED in call to LsaCallAuthenticationPackage, status %x\n", Status ));
}
if (NT_SUCCESS(Status)) {
//
// Success
//
Result = TimeoutMessageBox(hDlg,
IDS_PASSWORD_CHANGED,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONINFORMATION,
TIMEOUT_CURRENT);
} else {
ReturnResult = MSGINA_DLG_FAILURE;
//
// Failure, explain it to the user
//
Result = HandleFailedChangePassword(hDlg,
Status,
UserName,
Domain,
pChangePasswordResponse
);
}
//
// Only call other providers if the change password attempt succeeded.
//
if (NT_SUCCESS(Status)) {
//
// Let other providers know about the change
//
//
// If the domain is one from our combo-box
// then it is valid for logons.
//
if (CB_ERR != SendMessage(GetDlgItem(hDlg, IDD_CHANGEPWD_DOMAIN),
CB_FINDSTRINGEXACT,
(WPARAM)-1,
(LPARAM)Domain)) {
ChangeInfo |= WN_VALID_LOGON_ACCOUNT;
}
//
// Hide this dialog and pass our parent as the owner
// of any provider dialogs
//
ShowWindow(hDlg, SW_HIDE);
hwndOwner = GetParent(hDlg);
MprInfo.pszUserName = DupString(UserName);
MprInfo.pszDomain = DupString(Domain);
MprInfo.pszPassword = DupString(NewPassword);
MprInfo.pszOldPassword = DupString(Password);
MprResult = pWlxFuncs->WlxChangePasswordNotify(
hGlobalWlx,
&MprInfo,
ChangeInfo | WN_NT_PASSWORD_CHANGED);
}
//
// Free up the return buffer
//
if (pChangePasswordResponse != NULL) {
LsaFreeReturnBuffer(pChangePasswordResponse);
}
//
// Find out what happened to the message box:
//
if ( Result != IDOK )
{
//
// mbox was interrupted
//
ReturnResult = SetInterruptFlag( ReturnResult );
}
return(ReturnResult);
}
/****************************************************************************\
*
* FUNCTION: HandleFailedChangePassword
*
* PURPOSE: Tells the user why their change-password attempt failed.
*
* RETURNS: MSGINA_DLG_FAILURE - we told them what the problem was successfully.
* DLG_INTERRUPTED() - a set of return values - see winlogon.h
*
* HISTORY:
*
* 21-Sep-92 Davidc Created.
*
\****************************************************************************/
DLG_RETURN_TYPE
HandleFailedChangePassword(
HWND hDlg,
NTSTATUS Status,
PWCHAR UserName,
PWCHAR Domain,
PMSV1_0_CHANGEPASSWORD_RESPONSE pChangePasswordResponse
)
{
DLG_RETURN_TYPE Result;
TCHAR Buffer1[MAX_STRING_BYTES];
TCHAR Buffer2[MAX_STRING_BYTES];
switch (Status) {
case STATUS_CANT_ACCESS_DOMAIN_INFO:
case STATUS_NO_SUCH_DOMAIN:
LoadString(hDllInstance, IDS_CHANGE_PWD_NO_DOMAIN, Buffer1, sizeof(Buffer1));
_snwprintf(Buffer2, sizeof(Buffer2), Buffer1, Domain);
LoadString(hDllInstance, IDS_CHANGE_PASSWORD, Buffer1, sizeof(Buffer1));
Result = TimeoutMessageBoxlpstr(hDlg, Buffer2,
Buffer1,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
case STATUS_NO_SUCH_USER:
case STATUS_WRONG_PASSWORD_CORE:
case STATUS_WRONG_PASSWORD:
Result = TimeoutMessageBox(hDlg, IDS_INCORRECT_NAME_OR_PWD_CHANGE,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
// Force re-entry of the old password
if (GetWindowLong(GetDlgItem(hDlg, IDD_CHANGEPWD_OLD), GWL_STYLE) & WS_VISIBLE) {
SetDlgItemText(hDlg, IDD_CHANGEPWD_OLD, NULL);
}
break;
case STATUS_ACCESS_DENIED:
Result = TimeoutMessageBox(hDlg, IDS_NO_PERMISSION_CHANGE_PWD,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
case STATUS_ACCOUNT_RESTRICTION:
Result = TimeoutMessageBox(hDlg, IDS_ACCOUNT_RESTRICTION_CHANGE,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
case STATUS_BACKUP_CONTROLLER:
Result = TimeoutMessageBox(hDlg, IDS_REQUIRES_PRIMARY_CONTROLLER,
IDS_CHANGE_PASSWORD,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
case STATUS_PASSWORD_RESTRICTION:
if (pChangePasswordResponse->PasswordInfoValid) {
LoadString(hDllInstance, IDS_PASSWORD_SPEC, Buffer1, sizeof(Buffer1));
_snwprintf(Buffer2, sizeof(Buffer2), Buffer1,
pChangePasswordResponse->DomainPasswordInfo.MinPasswordLength,
pChangePasswordResponse->DomainPasswordInfo.PasswordHistoryLength
);
} else {
LoadString(hDllInstance, IDS_GENERAL_PASSWORD_SPEC, Buffer2, sizeof(Buffer2));
}
LoadString(hDllInstance, IDS_ENTER_PASSWORDS, Buffer1, sizeof(Buffer1));
wcsncat(Buffer2, TEXT(" "), sizeof(Buffer2) - sizeof(TCHAR)*(lstrlen(Buffer2) - 1));
wcsncat(Buffer2, Buffer1, sizeof(Buffer2) - sizeof(TCHAR)*(lstrlen(Buffer2) - 1));
LoadString(hDllInstance, IDS_CHANGE_PASSWORD, Buffer1, sizeof(Buffer1));
Result = TimeoutMessageBoxlpstr(hDlg, Buffer2,
Buffer1,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
#ifdef LATER
//
// LATER Check for minimum password age
//
if ( FALSE ) {
int PasswordAge = 0, RequiredAge = 0;
TCHAR Buffer1[MAX_STRING_BYTES];
TCHAR Buffer2[MAX_STRING_BYTES];
LoadString(hDllInstance, IDS_PASSWORD_MINIMUM_AGE, Buffer1, sizeof(Buffer1));
_snwprintf(Buffer2, sizeof(Buffer2), Buffer1, PasswordAge, RequiredAge);
LoadString(hDllInstance, IDS_NO_PERMISSION_CHANGE_PWD, Buffer1, sizeof(Buffer1));
lstrcat(Buffer1, TEXT(" "));
lstrcat(Buffer1, Buffer2);
LoadString(hDllInstance, IDS_CHANGE_PASSWORD, Buffer2, sizeof(Buffer2));
Result = TimeoutMessageBoxlpstr(hDlg, Buffer1,
Buffer2,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
}
#endif
default:
DebugLog((DEB_ERROR, "Change password failure status = 0x%lx", Status));
LoadString(hDllInstance, IDS_UNKNOWN_CHANGE_PWD_FAILURE, Buffer1, sizeof(Buffer1));
_snwprintf(Buffer2, sizeof(Buffer2), Buffer1, Status);
LoadString(hDllInstance, IDS_CHANGE_PASSWORD, Buffer1, sizeof(Buffer1));
Result = TimeoutMessageBoxlpstr(hDlg, Buffer2,
Buffer1,
MB_OK | MB_ICONEXCLAMATION,
TIMEOUT_CURRENT);
break;
}
return(Result);
UNREFERENCED_PARAMETER(UserName);
}
/***************************************************************************\
* FUNCTION: ChangePasswordHelpDlgProc
*
* PURPOSE: Processes messages for change password help dialog
*
* RETURNS: MSGINA_DLG_SUCCESS - the dialog was shown and dismissed successfully.
* MSGINA_DLG_FAILURE - the dialog could not be shown
* DLG_INTERRUPTED() - a set defined in winlogon.h
*
* HISTORY:
*
* 3-17-93 Robertre Created.
*
\***************************************************************************/
BOOL WINAPI
ChangePasswordHelpDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
PGLOBALS pGlobals = (PGLOBALS)GetWindowLong(hDlg, GWL_USERDATA);
switch (message) {
case WM_INITDIALOG:
SetWindowLong(hDlg, GWL_USERDATA, lParam);
CentreWindow(hDlg);
return(TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
case IDOK:
EndDialog(hDlg, MSGINA_DLG_SUCCESS);
return(TRUE);
}
break;
}
// We didn't process this message
return FALSE;
}