/****************************** 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 #include // #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; }