/*++ Copyright (c) 1993, 1994 Microsoft Corporation Module Name: nwdlg.c Abstract: This module contains NetWare Network Provider Dialog code. It contains all functions used in handling the dialogs shown by the provider. Author: Yi-Hsin Sung (yihsins) 5-July-1993 Split from provider.c Revision History: Rita Wong (ritaw) 10-Apr-1994 Added change password functionality. --*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NW_ENUM_EXTRA_BYTES 256 #define IS_TREE(p) (*p == TREE_CHAR) //-------------------------------------------------------------------// // // // Local Function Prototypes // // // //-------------------------------------------------------------------// VOID NwpAddToComboBox( IN HWND DialogHandle, IN INT ControlId, IN LPWSTR pszNone OPTIONAL, IN BOOL AllowNone ); BOOL WINAPI NwpConnectDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ); VOID NwpCenterDialog( IN HWND hwnd ); HWND NwpGetParentHwnd( VOID ); VOID NwpGetNoneString( LPWSTR pszNone, DWORD cBufferSize ); VOID NwpAddNetWareTreeConnectionsToList( IN HWND DialogHandle, IN LPWSTR NtUserName, IN LPDWORD lpdwUserLuid, IN INT ControlId ); VOID NwpAddServersToControl( IN HWND DialogHandle, IN INT ControlId, IN UINT Message, IN INT ControlIdMatch OPTIONAL, IN UINT FindMessage ); VOID NwpAddTreeNamesToControl( IN HWND DialogHandle, IN INT ControlId, IN UINT Message, IN INT ControlIdMatch OPTIONAL, IN UINT FindMessage ); DWORD NwpGetTreesAndChangePw( IN HWND DialogHandle, IN LPWSTR ServerBuf, IN DWORD UserLuid, IN PCHANGE_PW_DLG_PARAM Credential ); BOOL WINAPI NwpOldPasswordDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ); BOOL WINAPI NwpAltUserNameDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ); VOID EnableAddRemove( IN HWND DialogHandle ); BOOL WINAPI NwpLoginDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This function is the window management message handler which initializes, and reads user input from the login dialog. It also checks that the preferred server name is valid, notifies the user if not, and dismisses the dialog when done. Arguments: DialogHandle - Supplies a handle to the login dialog. Message - Supplies the window management message. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { static PLOGINDLGPARAM pLoginParam; static WCHAR OrigPassword[NW_MAX_SERVER_LEN + 1]; static WCHAR pszNone[64]; DWORD status = NO_ERROR; DWORD dwNoneIndex = 0; BOOL enableServer = TRUE ; switch (Message) { case WM_INITDIALOG: pLoginParam = (PLOGINDLGPARAM) LParam; // // Store the original password // wcscpy( OrigPassword, pLoginParam->Password ); // // Position dialog // NwpCenterDialog(DialogHandle); // // Handle logon script button // if ( pLoginParam->LogonScriptOptions & NW_LOGONSCRIPT_ENABLED ) CheckDlgButton( DialogHandle, ID_LOGONSCRIPT, 1 ); else CheckDlgButton( DialogHandle, ID_LOGONSCRIPT, 0 ); // // Username. Just display the original. // SetDlgItemTextW(DialogHandle, ID_USERNAME, pLoginParam->UserName); // // Initialize the string. // NwpGetNoneString( pszNone, sizeof( pszNone) ); // // Set the values in combo-box list. // NwpAddToComboBox(DialogHandle, ID_SERVER, pszNone, TRUE); // // Initially, select the last entry in server list, which should // be the entry. // dwNoneIndex = SendDlgItemMessageW( DialogHandle, ID_SERVER, CB_GETCOUNT, 0, 0 ); if ( dwNoneIndex != CB_ERR && dwNoneIndex > 0 ) dwNoneIndex -= 1; (void) SendDlgItemMessageW( DialogHandle, ID_SERVER, CB_SETCURSEL, dwNoneIndex == CB_ERR ? 0 : dwNoneIndex, 0 ); // // Display the previously saved preferred server or context. // Also set appropriate radio button // if ( *(pLoginParam->ServerName) != NW_INVALID_SERVER_CHAR ) { if ( !IS_TREE(pLoginParam->ServerName) ) { // // regular server // if (SendDlgItemMessageW( DialogHandle, ID_SERVER, CB_SELECTSTRING, 0, (LPARAM) pLoginParam->ServerName ) == CB_ERR) { // // Did not find preferred server in the combo-box, // just set the old value in the edit item. // SetDlgItemTextW( DialogHandle, ID_SERVER, pLoginParam->ServerName); } } else { // // we are dealing with *tree\context. break it into // tree and context // WCHAR *pszTmp = wcschr(pLoginParam->ServerName + 1, L'\\') ; if (pszTmp) *pszTmp = 0 ; SetDlgItemTextW( DialogHandle, ID_DEFAULTTREE, pLoginParam->ServerName + 1); SetDlgItemTextW( DialogHandle, ID_DEFAULTCONTEXT, pszTmp ? (pszTmp + 1) : L""); if (pszTmp) *pszTmp = L'\\' ; // restore the '\' enableServer = FALSE ; } } // // enable appropriate buttons // CheckRadioButton( DialogHandle, ID_PREFERREDSERVER_RB, ID_DEFAULTCONTEXT_RB, enableServer ? ID_PREFERREDSERVER_RB : ID_DEFAULTCONTEXT_RB) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_SERVER ), enableServer ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTTREE ), !enableServer ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTCONTEXT ), !enableServer ) ; SetFocus ( GetDlgItem ( DialogHandle, enableServer ? ID_SERVER : ID_DEFAULTTREE ) ) ; // // Preferred server name is limited to 48 characters. // Tree is limited to 32. We limit context to 256 - MAXTREE - 3 // SendDlgItemMessageW( DialogHandle, ID_SERVER, CB_LIMITTEXT, NW_MAX_SERVER_LEN - 1, 0 ); SendDlgItemMessageW( DialogHandle, ID_DEFAULTTREE, EM_LIMITTEXT, NW_MAX_TREE_LEN - 1, 0 ); SendDlgItemMessageW( DialogHandle, ID_DEFAULTCONTEXT, EM_LIMITTEXT, (256 - NW_MAX_TREE_LEN) - 4, // -4 for backslashes unc style 0 ); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case ID_DEFAULTCONTEXT_RB : if ( (HIWORD(WParam) == BN_CLICKED ) || (HIWORD(WParam) == BN_DOUBLECLICKED ) ) { CheckRadioButton( DialogHandle, ID_PREFERREDSERVER_RB, ID_DEFAULTCONTEXT_RB, ID_DEFAULTCONTEXT_RB) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_SERVER ), FALSE ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTTREE ), TRUE ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTCONTEXT ), TRUE ) ; SetFocus ( GetDlgItem ( DialogHandle, ID_DEFAULTTREE ) ) ; } break ; case ID_PREFERREDSERVER_RB : if ( (HIWORD(WParam) == BN_CLICKED ) || (HIWORD(WParam) == BN_DOUBLECLICKED ) ) { CheckRadioButton( DialogHandle, ID_PREFERREDSERVER_RB, ID_DEFAULTCONTEXT_RB, ID_PREFERREDSERVER_RB) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_SERVER ), TRUE ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTTREE ), FALSE ) ; EnableWindow ( GetDlgItem ( DialogHandle, ID_DEFAULTCONTEXT ), FALSE ) ; SetFocus ( GetDlgItem ( DialogHandle, ID_SERVER ) ) ; } break ; // // Use the user's original password when // the user types in or selects a new server or context // case ID_DEFAULTTREE: case ID_DEFAULTCONTEXT: if ( HIWORD(WParam) == EN_CHANGE ) { wcscpy( pLoginParam->Password, OrigPassword ); } break; case ID_SERVER: if ( (HIWORD(WParam) == CBN_EDITCHANGE ) || (HIWORD(WParam) == CBN_SELCHANGE ) ) { wcscpy( pLoginParam->Password, OrigPassword ); } break; case IDOK: { LPWSTR pszLocation = NULL; ASSERT(pLoginParam->ServerNameSize >= MAX_PATH) ; // // Allocate a buffer big enough to hold the Preferred // Server name or the NDS Tree and context in the form: // *Tree(Context). Therefore we allocate twice the space // needed for a UNICODE Server name. // if ((pszLocation = LocalAlloc(LMEM_ZEROINIT, (pLoginParam->ServerNameSize * sizeof(WCHAR) * 2)) ) == NULL ) { break; } // // Read the server or tree/context and validate its value. // if (IsDlgButtonChecked(DialogHandle, ID_DEFAULTCONTEXT_RB)) { // // We are dealing with TREE/CONTEXT. Synthesize string // in "*TREE\CONTEXT" format. // WCHAR *pTmp ; *pszLocation = TREE_CHAR ; if (!GetDlgItemTextW( DialogHandle, ID_DEFAULTTREE, pszLocation + 1, pLoginParam->ServerNameSize - 1 )) { // // The tree name field was blank! // Prompt user to provide a NDS tree name. // LocalFree( pszLocation ); (void) NwpMessageBoxError( DialogHandle, IDS_AUTH_FAILURE_TITLE, IDS_TREE_NAME_MISSING, 0, NULL, MB_OK | MB_ICONSTOP ); // // Put the focus where the user can fix the // invalid tree name. // SetFocus(GetDlgItem(DialogHandle,ID_DEFAULTTREE)); SendDlgItemMessageW( DialogHandle, ID_DEFAULTTREE, EM_SETSEL, 0, MAKELPARAM(0, -1) ); return TRUE; } pTmp = pszLocation + wcslen( pszLocation ); *pTmp++ = L'\\' ; if (!GetDlgItemTextW( DialogHandle, ID_DEFAULTCONTEXT, pTmp, pLoginParam->ServerNameSize - (pTmp-pszLocation) )) { // // The context name field was blank! // Prompt user to provide a NDS context name. // LocalFree( pszLocation ); (void) NwpMessageBoxError( DialogHandle, IDS_AUTH_FAILURE_TITLE, IDS_CONTEXT_MISSING, 0, NULL, MB_OK | MB_ICONSTOP ); // // Put the focus where the user can fix the // invalid context name. // SetFocus(GetDlgItem(DialogHandle,ID_DEFAULTCONTEXT)); SendDlgItemMessageW( DialogHandle, ID_DEFAULTCONTEXT, EM_SETSEL, 0, MAKELPARAM(0, -1) ); return TRUE; } } else { // // Straight server. Just read it in. If we cant get it // or is empty, use . // if (GetDlgItemTextW( DialogHandle, ID_SERVER, pszLocation, pLoginParam->ServerNameSize ) == 0) { wcscpy( pszLocation, pszNone ); } } if (( lstrcmpi( pszLocation, pszNone ) != 0) && ( !IS_TREE( pszLocation )) && ( !IS_VALID_TOKEN( pszLocation,wcslen( pszLocation )))) { // // Put up message box complaining about the bad // server name. // (void) NwpMessageBoxError( DialogHandle, IDS_AUTH_FAILURE_TITLE, IDS_INVALID_SERVER, 0, NULL, MB_OK | MB_ICONSTOP ); // // Put the focus where the user can fix the // invalid name. // SetFocus(GetDlgItem(DialogHandle, ID_SERVER)); SendDlgItemMessageW( DialogHandle, ID_SERVER, EM_SETSEL, 0, MAKELPARAM(0, -1) ); return TRUE; } // // If the user select , // change it to empty string. // if (lstrcmpi( pszLocation, pszNone) == 0) { wcscpy( pszLocation, L"" ); } #if DBG IF_DEBUG(LOGON) { KdPrint(("\n\t[OK] was pressed\n")); KdPrint(("\tNwrLogonUser\n")); KdPrint(("\tPassword : %ws\n",pLoginParam->Password)); KdPrint(("\tServer : %ws\n",pszLocation )); } #endif while(1) { PROMPTDLGPARAM PasswdPromptParam; INT Result ; // // make sure this user is logged off // (void) NwrLogoffUser( NULL, pLoginParam->pLogonId ); status = NwrLogonUser( NULL, pLoginParam->pLogonId, pLoginParam->UserName, pLoginParam->Password, pszLocation, NULL, 0 ); if (status != ERROR_INVALID_PASSWORD) break ; PasswdPromptParam.UserName = pLoginParam->UserName, PasswdPromptParam.ServerName = pszLocation; PasswdPromptParam.Password = pLoginParam->Password; PasswdPromptParam.PasswordSize = pLoginParam->PasswordSize ; Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_PASSWORD_PROMPT), (HWND) DialogHandle, NwpPasswdPromptDlgProc, (LPARAM) &PasswdPromptParam ); if (Result == -1 || Result == IDCANCEL) { status = ERROR_INVALID_PASSWORD ; break ; } } if (status == NW_PASSWORD_HAS_EXPIRED) { WCHAR szNumber[16] ; DWORD dwMsgId, dwGraceLogins = 0 ; LPWSTR apszInsertStrings[3] ; // // get the grace login count // if (!IS_TREE(pszLocation)) { DWORD status1 ; status1 = NwGetGraceLoginCount( pszLocation, pLoginParam->UserName, &dwGraceLogins) ; // // if hit error, just dont use the number // if (status1 == NO_ERROR) { dwMsgId = IDS_PASSWORD_HAS_EXPIRED ; wsprintfW(szNumber, L"%ld", dwGraceLogins) ; } else { dwMsgId = IDS_PASSWORD_HAS_EXPIRED1 ; } } else // BUGBUG - should get proper number { dwMsgId = IDS_PASSWORD_HAS_EXPIRED1 ; } apszInsertStrings[0] = pszLocation ; apszInsertStrings[1] = szNumber ; apszInsertStrings[2] = NULL ; // // put up message on password expiry // (void) NwpMessageBoxIns( (HWND) DialogHandle, IDS_NETWARE_TITLE, dwMsgId, apszInsertStrings, MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION ); status = NO_ERROR ; } // // Check the LogonScript check box. // if (IsDlgButtonChecked(DialogHandle, ID_LOGONSCRIPT)) { pLoginParam->LogonScriptOptions = NW_LOGONSCRIPT_ENABLED | NW_LOGONSCRIPT_4X_ENABLED ; } else { pLoginParam->LogonScriptOptions = NW_LOGONSCRIPT_DISABLED ; } if (status == NO_ERROR) { // // Save the logon credential to the registry // NwpSaveLogonCredential( pLoginParam->NewUserSid, pLoginParam->pLogonId, pLoginParam->UserName, pLoginParam->Password, pszLocation ); // Clear the password buffer RtlZeroMemory( OrigPassword, sizeof( OrigPassword)); NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions ); EndDialog(DialogHandle, 0); } else { INT nResult; DWORD dwMsgId = IDS_AUTH_FAILURE_WARNING; WCHAR *pszErrorLocation = pszLocation ; if (status == ERROR_ACCOUNT_RESTRICTION) { dwMsgId = IDS_AUTH_ACC_RESTRICTION; } if (status == ERROR_SHARING_PAUSED) { status = IDS_LOGIN_DISABLED; } if (IS_TREE(pszLocation)) { // // Format into nicer string for user // WCHAR *pszTmp = LocalAlloc(LMEM_ZEROINIT, (wcslen(pszLocation)+2) * sizeof(WCHAR)) ; if (pszTmp) { pszErrorLocation = pszTmp ; // // This code formats the NDS // tree UNC to: Tree(Context) // wcscpy(pszErrorLocation, pszLocation+1) ; if (pszTmp = wcschr(pszErrorLocation, L'\\')) { *pszTmp = L'(' ; wcscat(pszErrorLocation, L")") ; } } } nResult = NwpMessageBoxError( DialogHandle, IDS_AUTH_FAILURE_TITLE, dwMsgId, status, pszErrorLocation, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION ); if (pszErrorLocation != pszLocation) { (void) LocalFree(pszErrorLocation) ; } if ( nResult == IDYES ) { // // Save the logon credential to the registry // NwpSaveLogonCredential( pLoginParam->NewUserSid, pLoginParam->pLogonId, pLoginParam->UserName, pLoginParam->Password, pszLocation ); // Clear the password buffer RtlZeroMemory( OrigPassword, sizeof( OrigPassword)); NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions ); EndDialog(DialogHandle, 0); } else { // // Put the focus where the user can fix the // invalid name. // DWORD controlId = IsDlgButtonChecked(DialogHandle, ID_DEFAULTCONTEXT_RB) ? ID_DEFAULTTREE : ID_SERVER ; SetFocus(GetDlgItem(DialogHandle, controlId)); SendDlgItemMessageW( DialogHandle, controlId, EM_SETSEL, 0, MAKELPARAM(0, -1) ); } } LocalFree( pszLocation ); return TRUE; } case IDCANCEL: #if DBG IF_DEBUG(LOGON) { KdPrint(("\n\t[CANCEL] was pressed\n")); KdPrint(("\tLast Preferred Server: %ws\n", pLoginParam->ServerName)); KdPrint(("\tLast Password: %ws\n", pLoginParam->Password )); } #endif if ( *(pLoginParam->ServerName) == NW_INVALID_SERVER_CHAR ) { // No preferred server has been set. // Pop up a warning to the user. INT nResult = NwpMessageBoxError( DialogHandle, IDS_NETWARE_TITLE, IDS_NO_PREFERRED, 0, NULL, MB_YESNO | MB_ICONEXCLAMATION ); // // The user chose NO, return to the dialog. // if ( nResult == IDNO ) { // // Put the focus where the user can fix the // invalid name. // DWORD controlId = IsDlgButtonChecked(DialogHandle, ID_DEFAULTCONTEXT_RB) ? ID_DEFAULTTREE : ID_SERVER ; SetFocus(GetDlgItem(DialogHandle, controlId)); SendDlgItemMessageW( DialogHandle, controlId, EM_SETSEL, 0, MAKELPARAM(0, -1) ); return TRUE; } // // Save the preferred server as empty string // NwpSaveLogonCredential( pLoginParam->NewUserSid, pLoginParam->pLogonId, pLoginParam->UserName, pLoginParam->Password, L"" ); pLoginParam->LogonScriptOptions = NW_LOGONSCRIPT_DISABLED; NwpSaveLogonScriptOptions( pLoginParam->NewUserSid, pLoginParam->LogonScriptOptions ); } // The user has not logged on to any server. // Logged the user on using NULL as preferred server. NwrLogonUser( NULL, pLoginParam->pLogonId, pLoginParam->UserName, pLoginParam->Password, NULL, NULL, 0 ); // // Clear the password buffer RtlZeroMemory( OrigPassword, sizeof( OrigPassword)); EndDialog(DialogHandle, 0); return TRUE; case IDHELP: { INT Result ; Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_PREFERRED_SERVER_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); // ignore any errors. should not fail, and if does, // nothing we can do. return TRUE ; } } } // // We didn't process this message // return FALSE; } INT NwpMessageBoxError( IN HWND hwndParent, IN DWORD TitleId, IN DWORD BodyId, IN DWORD Error, IN LPWSTR pszParameter, IN UINT Style ) /*++ Routine Description: This routine puts up a message box error. Arguments: hwndParent - Supplies the handle of the parent window. TitleId - Supplies the ID of the title. ( LoadString ) BodyId - Supplies the ID of the message. ( LoadString ) Error - If BodyId != 0, then this supplies the ID of the substitution string that will be substituted into the string indicated by BodyId. If BodyId == 0, then this will be the error message. This id is a system error that we will get from FormatMessage using FORMAT_MESSAGE_FROM_SYSTEM. pszParameter - A substitution string that will be used as %2 or if Error == 0, this string will be substituted as %1 into the string indicated by BodyId. Style - Supplies the style of the MessageBox. Return Value: The return value from the MessageBox, 0 if any error is encountered. --*/ { DWORD nResult = 0; DWORD nLength; WCHAR szTitle[MAX_PATH]; WCHAR szBody[MAX_PATH]; LPWSTR pszError = NULL; LPWSTR pszBuffer = NULL; szTitle[0] = 0; szBody[0] = 0; // // Get the Title string // nLength = LoadStringW( hmodNW, TitleId, szTitle, sizeof(szTitle) / sizeof(WCHAR) ); if ( nLength == 0) { KdPrint(("NWPROVAU: LoadStringW of Title failed with %lu\n", GetLastError())); return 0; } // // Get the body string, if BodyId != 0 // if ( BodyId != 0 ) { nLength = LoadStringW( hmodNW, BodyId, szBody, sizeof(szBody) / sizeof(WCHAR) ); if ( nLength == 0) { KdPrint(("NWPROVAU: LoadStringW of Body failed with %lu\n", GetLastError())); return 0; } } if ( (Error >= IDS_START) && (Error <= IDS_END) ) { pszError = (WCHAR *) LocalAlloc( LPTR, 256 * sizeof(WCHAR)) ; if (!pszError) return 0 ; nLength = LoadStringW( hmodNW, Error, pszError, 256 ); if ( nLength == 0 ) { KdPrint(("NWPROVAU: LoadStringW of Error failed with %lu\n", GetLastError())); (void) LocalFree( (HLOCAL)pszError) ; return 0; } } else if ( Error != 0 ) { if ( ( Error == WN_NO_MORE_ENTRIES ) || ( Error == ERROR_MR_MID_NOT_FOUND )) { // // Handle bogus error from the redirector // KdPrint(("NWPROVAU: The NetwareRedirector returned a bogus error as the reason for failure to authenticate. (See Kernel Debugger)\n")); } nLength = FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, Error, 0, (LPWSTR) &pszError, MAX_PATH, NULL ); if ( nLength == 0 ) { KdPrint(("NWPROVAU: FormatMessageW of Error failed with %lu\n", GetLastError())); return 0; } } if ( ( *szBody != 0 ) && ( ( pszError != NULL ) || ( pszParameter != NULL) )) { LPWSTR aInsertStrings[2]; aInsertStrings[0] = pszError? pszError : pszParameter; aInsertStrings[1] = pszError? pszParameter : NULL; nLength = FormatMessageW( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, szBody, 0, // Ignored 0, // Ignored (LPWSTR) &pszBuffer, MAX_PATH, (va_list *) aInsertStrings ); if ( nLength == 0 ) { KdPrint(("NWPROVAU:FormatMessageW(insertstring) failed with %lu\n", GetLastError())); if ( pszError != NULL ) (void) LocalFree( (HLOCAL) pszError ); return 0; } } else if ( *szBody != 0 ) { pszBuffer = szBody; } else if ( pszError != NULL ) { pszBuffer = pszError; } else { // We have neither the body nor the error string. // Hence, don't popup the messagebox return 0; } if ( pszBuffer != NULL ) { nResult = MessageBoxW( hwndParent, pszBuffer, szTitle, Style ); } if ( ( pszBuffer != NULL ) && ( pszBuffer != szBody ) && ( pszBuffer != pszError )) { (void) LocalFree( (HLOCAL) pszBuffer ); } if ( pszError != NULL ) (void) LocalFree( (HLOCAL) pszError ); return nResult; } INT NwpMessageBoxIns( IN HWND hwndParent, IN DWORD TitleId, IN DWORD MessageId, IN LPWSTR *InsertStrings, IN UINT Style ) /*++ Routine Description: This routine puts up a message box error with array of insert strings Arguments: hwndParent - Supplies the handle of the parent window. TitleId - Supplies the ID of the title. ( LoadString ) MessageId - Supplies the ID of the message. ( LoadString ) InsertStrings - Array of insert strings for FormatMessage. Style - Supplies the style of the MessageBox. Return Value: The return value from the MessageBox, 0 if any error is encountered. --*/ { DWORD nResult = 0; DWORD nLength; WCHAR szTitle[MAX_PATH]; WCHAR szBody[MAX_PATH]; LPWSTR pszBuffer = NULL; szTitle[0] = 0; szBody[0] = 0; // // Get the Title string // nLength = LoadStringW( hmodNW, TitleId, szTitle, sizeof(szTitle) / sizeof(szTitle[0]) ); if ( nLength == 0) { return 0; } // // Get the message string // nLength = LoadStringW( hmodNW, MessageId, szBody, sizeof(szBody) / sizeof(szBody[0]) ); if ( nLength == 0) { return 0; } nLength = FormatMessageW( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, szBody, 0, // Ignored 0, // Ignored (LPWSTR) &pszBuffer, MAX_PATH, (va_list *) InsertStrings ); if ( nLength == 0 ) { return 0; } if ( pszBuffer != NULL ) { nResult = MessageBoxW( hwndParent, pszBuffer, szTitle, Style ); (void) LocalFree( (HLOCAL) pszBuffer ); } return nResult; } VOID NwpAddServersToControl( IN HWND DialogHandle, IN INT ControlId, IN UINT Message, IN INT ControlIdMatch OPTIONAL, IN UINT FindMessage ) /*++ Routine Description: This function enumerates the servers on the network and adds each server name to the specified Windows control. If ControlIdMatch is specified (i.e. non 0), only servers that are not found in ControlIdMatch list are added to the list specified by ControlId. Arguments: DialogHandle - Supplies a handle to the Windows dialog. ControlId - Supplies id which specifies the control. Message - Supplies the window management message to add string. ControlIdMatch - Supplies the control ID which contains server names that should not be in ControlId. FindMessage - Supplies the window management message to find string. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { DWORD status = ERROR_NO_NETWORK; HANDLE EnumHandle = (HANDLE) NULL; LPNETRESOURCE NetR = NULL; LPNETRESOURCEW SavePtr; WCHAR FormattedNameBuf[MAX_NDS_NAME_CHARS]; LPWSTR lpFormattedName; DWORD dwLength; DWORD BytesNeeded = 512; DWORD EntriesRead; DWORD i; // // Retrieve the list of servers on the network // status = NPOpenEnum( RESOURCE_GLOBALNET, 0, 0, NULL, &EnumHandle ); if (status != NO_ERROR) { EnumHandle = (HANDLE) NULL; goto CleanExit; } // // Allocate buffer to get servers on the net. // if ((NetR = (LPVOID) LocalAlloc( 0, BytesNeeded )) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto CleanExit; } do { EntriesRead = 0xFFFFFFFF; // Read as many as possible status = NPEnumResource( EnumHandle, &EntriesRead, (LPVOID) NetR, &BytesNeeded ); if (status == WN_SUCCESS) { SavePtr = NetR; for (i = 0; i < EntriesRead; i++, NetR++) { if ( NetR->dwDisplayType == RESOURCEDISPLAYTYPE_TREE) { continue; } else { lpFormattedName = FormattedNameBuf; } dwLength = NW_MAX_SERVER_LEN + 1; status = NPFormatNetworkName( NetR->lpRemoteName, lpFormattedName, &dwLength, WNFMT_INENUM, 0 ); lpFormattedName = FormattedNameBuf; if ( status != WN_SUCCESS ) { continue; } if ( dwLength > NW_MAX_SERVER_LEN + 1 ) { continue; } if (ControlIdMatch != 0) { INT Result; // // Add the server to list only if it's not found // in the alternate list specified by ControlIdMatch. // Result = SendDlgItemMessageW( DialogHandle, ControlIdMatch, FindMessage, (WPARAM) -1, (LPARAM) lpFormattedName ); if (Result == LB_ERR) { // // Server name not found. Add to list. // SendDlgItemMessageW( DialogHandle, ControlId, Message, 0, (LPARAM) lpFormattedName ); } } else { // // No alternate list. Just add all servers. // SendDlgItemMessageW( DialogHandle, ControlId, Message, 0, (LPARAM) lpFormattedName ); } } NetR = SavePtr; } else if (status != WN_NO_MORE_ENTRIES) { status = GetLastError(); if (status == WN_MORE_DATA) { // // Original buffer was too small. Free it and allocate // the recommended size and then some to get as many // entries as possible. // (void) LocalFree((HLOCAL) NetR); BytesNeeded += NW_ENUM_EXTRA_BYTES; if ((NetR = (LPVOID) LocalAlloc( 0, BytesNeeded )) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto CleanExit; } } else { goto CleanExit; } } } while (status != WN_NO_MORE_ENTRIES); if (status == WN_NO_MORE_ENTRIES) { status = NO_ERROR; } CleanExit: if (EnumHandle != (HANDLE) NULL) { (void) NPCloseEnum(EnumHandle); } if (NetR != NULL) { (void) LocalFree((HLOCAL) NetR); } } VOID NwpAddTreeNamesToControl( IN HWND DialogHandle, IN INT ControlId, IN UINT Message, IN INT ControlIdMatch OPTIONAL, IN UINT FindMessage ) /*++ Routine Description: This function enumerates the NDS tree on the network and adds each tree name to the specified Windows control. If ControlIdMatch is specified (i.e. non 0), only trees that are not found in ControlIdMatch list are added to the list specified by ControlId. Arguments: DialogHandle - Supplies a handle to the Windows dialog. ControlId - Supplies id which specifies the control. Message - Supplies the window management message to add string. ControlIdMatch - Supplies the control ID which contains server names that should not be in ControlId. FindMessage - Supplies the window management message to find string. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { DWORD status = ERROR_NO_NETWORK; HANDLE EnumHandle = (HANDLE) NULL; LPNETRESOURCE NetR = NULL; LPNETRESOURCEW SavePtr; WCHAR FormattedNameBuf[MAX_NDS_NAME_CHARS]; LPWSTR lpFormattedName; DWORD dwLength; DWORD BytesNeeded = 512; DWORD EntriesRead; DWORD i; // // Retrieve the list of trees on the network // status = NPOpenEnum( RESOURCE_GLOBALNET, 0, 0, NULL, &EnumHandle ); if (status != NO_ERROR) { EnumHandle = (HANDLE) NULL; goto CleanExit; } // // Allocate buffer to get trees on the net. // if ((NetR = (LPVOID) LocalAlloc( 0, BytesNeeded )) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto CleanExit; } do { EntriesRead = 0xFFFFFFFF; // Read as many as possible status = NPEnumResource( EnumHandle, &EntriesRead, (LPVOID) NetR, &BytesNeeded ); if (status == WN_SUCCESS) { SavePtr = NetR; for (i = 0; i < EntriesRead; i++, NetR++) { if ( NetR->dwDisplayType == RESOURCEDISPLAYTYPE_TREE) { lpFormattedName = (LPWSTR) FormattedNameBuf; } else { continue; } dwLength = NW_MAX_SERVER_LEN + 1; status = NPFormatNetworkName( NetR->lpRemoteName, lpFormattedName, &dwLength, WNFMT_INENUM, 0 ); lpFormattedName = FormattedNameBuf; if ( status != WN_SUCCESS ) { continue; } if ( dwLength > NW_MAX_SERVER_LEN + 1 ) { continue; } if (ControlIdMatch != 0) { INT Result; // // Add the server to list only if it's not found // in the alternate list specified by ControlIdMatch. // Result = SendDlgItemMessageW( DialogHandle, ControlIdMatch, FindMessage, (WPARAM) -1, (LPARAM) lpFormattedName ); if (Result == LB_ERR) { // // Server name not found. Add to list. // SendDlgItemMessageW( DialogHandle, ControlId, Message, 0, (LPARAM) lpFormattedName ); } } else { // // No alternate list. Just add all servers. // SendDlgItemMessageW( DialogHandle, ControlId, Message, 0, (LPARAM) lpFormattedName ); } } NetR = SavePtr; } else if (status != WN_NO_MORE_ENTRIES) { status = GetLastError(); if (status == WN_MORE_DATA) { // // Original buffer was too small. Free it and allocate // the recommended size and then some to get as many // entries as possible. // (void) LocalFree((HLOCAL) NetR); BytesNeeded += NW_ENUM_EXTRA_BYTES; if ((NetR = (LPVOID) LocalAlloc( 0, BytesNeeded )) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto CleanExit; } } else { goto CleanExit; } } } while (status != WN_NO_MORE_ENTRIES); if (status == WN_NO_MORE_ENTRIES) { status = NO_ERROR; } CleanExit: if (EnumHandle != (HANDLE) NULL) { (void) NPCloseEnum(EnumHandle); } if (NetR != NULL) { (void) LocalFree((HLOCAL) NetR); } } VOID NwpAddToComboBox( IN HWND DialogHandle, IN INT ControlId, IN LPWSTR pszNone OPTIONAL, IN BOOL AllowNone ) { NwpAddServersToControl(DialogHandle, ControlId, CB_ADDSTRING, 0, 0); // // Combo-box will contain at least the entry in its list. // if ( ARGUMENT_PRESENT(pszNone) && AllowNone) { SendDlgItemMessageW( DialogHandle, ControlId, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) pszNone ); } } DWORD NwpGetUserCredential( IN HWND hParent, IN LPWSTR Unc, IN DWORD err, IN LPWSTR pszConnectAsUserName, OUT LPWSTR *UserName, OUT LPWSTR *Password ) /*++ Routine Description: This function puts up a popup dialog for the user, whose default credential denied browse directory access, to enter the correct credential. If this function returns successful, the pointers to memory allocated for the user entered username and password are returned. Arguments: Unc - Supplies the container name in \\Server\Volume format under which the user wants to browse directories. UserName - Receives the pointer to memory allocated for the username gotten from the dialog. This pointer must be freed with LocalFree when done. Password - Receives the pointer to memory allocated for the password gotten from the dialog. This pointer must be freed with LocalFree when done. Return Value: NO_ERROR or reason for failure. --*/ { DWORD status; INT Result; HWND DialogHandle = hParent? hParent : NwpGetParentHwnd(); DWORD UserNameSize = NW_MAX_USERNAME_LEN + 1; DWORD PasswordSize = NW_MAX_PASSWORD_LEN + 1; CONNECTDLGPARAM ConnectParam; *UserName = NULL; *Password = NULL; if (DialogHandle == NULL) { return ERROR_WINDOW_NOT_DIALOG; } // // Allocate memory to return UserName and Password // if ((*UserName = (LPVOID) LocalAlloc( 0, UserNameSize * sizeof(WCHAR) )) == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } // // Allocate memory to return UserName and Password // if ((*Password = (LPVOID) LocalAlloc( 0, PasswordSize * sizeof(WCHAR) )) == NULL) { (void) LocalFree( *UserName ); *UserName = NULL; return ERROR_NOT_ENOUGH_MEMORY; } ConnectParam.UncPath = Unc; ConnectParam.ConnectAsUserName = pszConnectAsUserName; ConnectParam.UserName = *UserName; ConnectParam.Password = *Password; ConnectParam.UserNameSize = UserNameSize; ConnectParam.PasswordSize = PasswordSize; ConnectParam.LastConnectionError = err; Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_NETWORK_CREDENTIAL), DialogHandle, NwpConnectDlgProc, (LPARAM) &ConnectParam ); if ( Result == -1 ) { status = GetLastError(); KdPrint(("NWPROVAU: NwpGetUserCredential: DialogBox failed %lu\n", status)); goto ErrorExit; } else if ( Result == IDCANCEL ) { // // Cancel was pressed. // status = WN_CANCEL; goto ErrorExit; } return NO_ERROR; ErrorExit: (void) LocalFree((HLOCAL) *UserName); (void) LocalFree((HLOCAL) *Password); *UserName = NULL; *Password = NULL; return status; } BOOL WINAPI NwpConnectDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This function is the window management message handler which initializes, and reads user input from the dialog put up when the user fails to browse a directory on the default credential. Arguments: DialogHandle - Supplies a handle to display the dialog. Message - Supplies the window management message. LParam - Supplies the pointer to a buffer which on input contains the \\Server\Volume string under which the user needs to type in a new credential before browsing. On output, this pointer contains the username and password strings entered to the dialog box. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { static PCONNECTDLGPARAM pConnectParam; switch (Message) { case WM_INITDIALOG: pConnectParam = (PCONNECTDLGPARAM) LParam; // // Position dialog // // NwpCenterDialog(DialogHandle); // // Display the \\Server\Volume string. // SetDlgItemTextW( DialogHandle, ID_VOLUME_PATH, pConnectParam->UncPath ); if ( pConnectParam->LastConnectionError == NO_ERROR ) { WCHAR szTemp[256]; if ( LoadString( hmodNW, IDS_CONNECT_NO_ERROR_TEXT, szTemp, sizeof( szTemp )/sizeof(WCHAR))) { SetDlgItemTextW( DialogHandle, ID_CONNECT_TEXT, szTemp ); } } // // Username is limited to 256 characters. // SendDlgItemMessageW( DialogHandle, ID_CONNECT_AS, EM_LIMITTEXT, pConnectParam->UserNameSize - 1, // minus the space for '\0' 0 ); // // Password is limited to 256 characters. // SendDlgItemMessageW( DialogHandle, ID_CONNECT_PASSWORD, EM_LIMITTEXT, pConnectParam->PasswordSize - 1, // minus the space for '\0' 0 ); // // Display the User name string. // if ( pConnectParam->ConnectAsUserName ) { SetDlgItemTextW( DialogHandle, ID_CONNECT_AS, pConnectParam->ConnectAsUserName ); } return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDOK: GetDlgItemTextW( DialogHandle, ID_CONNECT_AS, pConnectParam->UserName, pConnectParam->UserNameSize ); GetDlgItemTextW( DialogHandle, ID_CONNECT_PASSWORD, pConnectParam->Password, pConnectParam->PasswordSize ); #if DBG IF_DEBUG(LOGON) { KdPrint(("\n\t[OK] was pressed\n")); KdPrint(("\tUserName : %ws\n", pConnectParam->UserName)); KdPrint(("\tPassword : %ws\n", pConnectParam->Password)); } #endif EndDialog(DialogHandle, (INT) IDOK); // OK return TRUE; case IDCANCEL: #if DBG IF_DEBUG(LOGON) { KdPrint(("\n\t[CANCEL] was pressed\n")); } #endif EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL return TRUE; case IDHELP: WinHelp( DialogHandle, NW_HELP_FILE, HELP_CONTEXT, IDH_DLG_NETWORK_CREDENTIAL_HELP ); return TRUE; } } // // We didn't process this message // return FALSE; } VOID NwpCenterDialog( HWND hwnd ) /*++ Routine Description: This routine positions the dialog centered horizontally and 1/3 down the screen vertically. It should be called by the dlg proc when processing the WM_INITDIALOG message. This code is stolen from Visual Basic written by GustavJ. Screen ----------------------------- | 1/3 Above | | --------------- | | | Dialog | | | | | | | --------------- | | 2/3 Below | | | ----------------------------- Arguments: hwnd - Supplies the handle to the dialog. Return Value: None. --*/ { RECT rect; LONG nx; // New x LONG ny; // New y LONG width; LONG height; GetWindowRect( hwnd, &rect ); width = rect.right - rect.left; height = rect.bottom - rect.top; nx = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; ny = (GetSystemMetrics(SM_CYSCREEN) - height) / 3; MoveWindow( hwnd, nx, ny, width, height, FALSE ); } HWND NwpGetParentHwnd( VOID ) /*++ Routine Description: This function gets the parent window handle so that a dialog can be displayed in the current context. Arguments: None. Return Value: Returns the parent window handle if successful; NULL otherwise. --*/ { HWND hwnd; LONG lWinStyle; // // Get the current focus. This is presumably the button // that was last clicked. // hwnd = GetFocus(); // // We must make sure that we don't return the window handle // for a child window. Hence, we traverse up the ancestors // of this window handle until we find a non-child window. // Then, we return that handle. If we ever find a NULL window // handle before finding a non-child window, we are unsuccessful // and will return NULL. // // Note on the bit manipulation below. A window is either // an overlapped window, a popup window or a child window. // Hence, we OR together the possible bit combinations of these // possibilities. This should tell us which bits are used in // the window style dword (although we know this becomes 0xC000 // today, we don't know if these will ever change later). Then, // we AND the bit combination we with the given window style // dword, and compare the result with WS_CHILD. This tells us // whether or not the given window is a child window. // while (hwnd) { lWinStyle = GetWindowLong (hwnd, GWL_STYLE); if ((lWinStyle & (WS_OVERLAPPED | WS_POPUP | WS_CHILD)) != WS_CHILD) { return hwnd; } hwnd = GetParent(hwnd); } return NULL; } BOOL WINAPI NwpPasswdPromptDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This function is the window management message handler for the change password dialog. Arguments: DialogHandle - Supplies a handle to display the dialog. Message - Supplies the window management message. LParam - Supplies the pointer to a buffer which on input contains the Server string under which the user needs to type in a new credential before browsing. On output, this pointer contains the username and server strings entered to the dialog box. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { LPWSTR UserName; LPWSTR ServerName; static LPWSTR Password; static DWORD PasswordSize ; INT Result ; PPROMPTDLGPARAM DlgParams ; DWORD nLength; WCHAR szLocation[MAX_PATH]; szLocation[0] = 0; switch (Message) { case WM_INITDIALOG: DlgParams = (PPROMPTDLGPARAM) LParam; UserName = DlgParams->UserName ; ServerName = DlgParams->ServerName ; Password = DlgParams->Password ; PasswordSize = DlgParams->PasswordSize ; ASSERT(ServerName) ; // // Position dialog // NwpCenterDialog(DialogHandle); // // Get the string "Server" or "Context". // nLength = LoadStringW( hmodNW, IS_TREE(ServerName) ? IDS_CONTEXT : IDS_SERVER, szLocation, sizeof(szLocation) / sizeof(szLocation[0]) ); if ( nLength == 0) { szLocation[0] = 0; // missing text, but still works } SetDlgItemTextW(DialogHandle, ID_LOCATION, szLocation); // // Format the server/context string. Note we reuse the // location buffer. // RtlZeroMemory(szLocation, sizeof(szLocation)) ; nLength = wcslen(ServerName) ; if ( IS_TREE(ServerName) && (nLength+1 < (sizeof(szLocation)/sizeof(szLocation[0])))) { // // NDS tree & context // WCHAR *pszTmp ; wcscpy(szLocation, ServerName+1) ; // skip the * if tree\context if (pszTmp = wcschr(szLocation, L'\\')) { *pszTmp = L'(' ; wcscat(szLocation, L")") ; } } else { wcsncpy(szLocation, ServerName, nLength) ; } // // show the user and server names. // SetDlgItemTextW(DialogHandle, ID_SERVER, szLocation); SetDlgItemTextW(DialogHandle, ID_USERNAME, UserName); // // set limits // SendDlgItemMessageW( DialogHandle, ID_PASSWORD, EM_LIMITTEXT, PasswordSize - 1, // minus space for '\0' 0 ); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDHELP: DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_PASSWORD_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); return TRUE; case IDOK: Result = GetDlgItemTextW( DialogHandle, ID_PASSWORD, Password, PasswordSize ); EndDialog(DialogHandle, (INT) IDOK); // OK return TRUE; case IDCANCEL: EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL return TRUE; } } // // We didn't process this message // return FALSE; } BOOL WINAPI NwpChangePasswordDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This function is the window management message handler for the change password dialog. Arguments: DialogHandle - Supplies a handle to display the dialog. Message - Supplies the window management message. LParam - Supplies the pointer to a buffer which on input contains the Server string under which the user needs to type in a new credential before browsing. On output, this pointer contains the username and server strings entered to the dialog box. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { static PCHANGE_PASS_DLG_PARAM pChangePassParam ; switch (Message) { case WM_INITDIALOG: pChangePassParam = (PCHANGE_PASS_DLG_PARAM) LParam; NwpCenterDialog(DialogHandle); SetDlgItemTextW(DialogHandle, ID_SERVER, pChangePassParam->TreeName); SetDlgItemTextW(DialogHandle, ID_USERNAME, pChangePassParam->UserName); // // set limits // SendDlgItemMessageW( DialogHandle, ID_OLD_PASSWORD, EM_LIMITTEXT, NW_MAX_PASSWORD_LEN, // minus space for '\0' 0 ); SendDlgItemMessageW( DialogHandle, ID_NEW_PASSWORD, EM_LIMITTEXT, NW_MAX_PASSWORD_LEN, // minus space for '\0' 0 ); SendDlgItemMessageW( DialogHandle, ID_CONFIRM_PASSWORD, EM_LIMITTEXT, NW_MAX_PASSWORD_LEN, // minus space for '\0' 0 ); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDHELP: DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); return TRUE; case IDOK: { INT Result; WCHAR szConfirmPassword[NW_MAX_PASSWORD_LEN + 1]; UNICODE_STRING OldPasswordStr; UNICODE_STRING NewPasswordStr; UCHAR EncodeSeed = NW_ENCODE_SEED2; Result = GetDlgItemTextW( DialogHandle, ID_OLD_PASSWORD, pChangePassParam->OldPassword, NW_MAX_PASSWORD_LEN ); Result = GetDlgItemTextW( DialogHandle, ID_NEW_PASSWORD, pChangePassParam->NewPassword, NW_MAX_PASSWORD_LEN ); Result = GetDlgItemTextW( DialogHandle, ID_CONFIRM_PASSWORD, szConfirmPassword, NW_MAX_PASSWORD_LEN ); if ( wcscmp( pChangePassParam->NewPassword, szConfirmPassword ) ) { // // New and Confirm passwords don't match! // (void) NwpMessageBoxError( DialogHandle, IDS_CHANGE_PASSWORD_TITLE, IDS_CHANGE_PASSWORD_CONFLICT, 0, NULL, MB_OK | MB_ICONSTOP ); SetDlgItemText( DialogHandle, ID_NEW_PASSWORD, L"" ); SetDlgItemText( DialogHandle, ID_CONFIRM_PASSWORD, L"" ); SetFocus( GetDlgItem( DialogHandle, ID_NEW_PASSWORD )); return TRUE; } RtlInitUnicodeString( &OldPasswordStr, pChangePassParam->OldPassword ); RtlInitUnicodeString( &NewPasswordStr, pChangePassParam->NewPassword ); RtlRunEncodeUnicodeString(&EncodeSeed, &OldPasswordStr); RtlRunEncodeUnicodeString(&EncodeSeed, &NewPasswordStr); EndDialog(DialogHandle, (INT) IDOK); // OK return TRUE; } case IDCANCEL: EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL return TRUE; default: return FALSE; } } // // We didn't process this message // return FALSE; } BOOL WINAPI NwpHelpDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) // // This dialog is used for both Help and Question dialogs. // { switch (Message) { case WM_INITDIALOG: NwpCenterDialog(DialogHandle); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDOK: case IDCANCEL: EndDialog(DialogHandle, IDOK); return TRUE; case IDYES: EndDialog(DialogHandle, IDYES); return TRUE; case IDNO: EndDialog(DialogHandle, IDNO); return TRUE; default: return FALSE ; } } // // We didn't process this message // return FALSE; } VOID NwpGetNoneString( LPWSTR pszNone, DWORD cBufferSize ) /*++ Routine Description: This function gets the string from the resource. Arguments: pszNone - Supplies the buffer to store the string. cBufferSize - Supplies the buffer size in bytes. Return Value: None. --*/ { INT TextLength; TextLength = LoadStringW( hmodNW, IDS_NONE, pszNone, cBufferSize / sizeof( WCHAR) ); if ( TextLength == 0 ) *pszNone = 0; } VOID NwpAddNetWareTreeConnectionsToList( IN HWND DialogHandle, IN LPWSTR NtUserName, IN LPDWORD lpdwUserLuid, IN INT ControlId ) { DWORD status = NO_ERROR; DWORD BufferSize = 2048; // 2KB Buffer BYTE pBuffer[2048]; DWORD EntriesRead; INT Result ; status = NwGetConnectedTrees( NtUserName, pBuffer, BufferSize, &EntriesRead, lpdwUserLuid ); if ( status == NO_ERROR && EntriesRead > 0 ) { PCONN_INFORMATION pConnInfo = (PCONN_INFORMATION) pBuffer; WCHAR tempTreeName[NW_MAX_TREE_LEN + 1]; DWORD dwSize; while ( EntriesRead-- ) { dwSize = sizeof( CONN_INFORMATION ); dwSize += pConnInfo->HostServerLength; dwSize += pConnInfo->UserNameLength; RtlZeroMemory( tempTreeName, ( NW_MAX_TREE_LEN + 1 ) * sizeof(WCHAR) ); wcsncpy( tempTreeName, pConnInfo->HostServer, pConnInfo->HostServerLength / sizeof(WCHAR) ); CharUpperW( tempTreeName ); // // Add the tree name to the list only // if it's not added already. // Result = SendDlgItemMessageW( DialogHandle, ControlId, LB_FINDSTRING, (WPARAM) -1, (LPARAM) tempTreeName ); if (Result == LB_ERR) { Result = SendDlgItemMessageW( DialogHandle, ControlId, LB_ADDSTRING, 0, (LPARAM) tempTreeName ); if (Result != LB_ERR) { LPWSTR lpNdsUserName = NULL; lpNdsUserName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT, pConnInfo->UserNameLength + sizeof(WCHAR) ); if ( lpNdsUserName ) { wcsncpy( lpNdsUserName, pConnInfo->UserName, pConnInfo->UserNameLength / sizeof(WCHAR) ); SendDlgItemMessageW( DialogHandle, ControlId, LB_SETITEMDATA, (WPARAM) Result, // index of entry (LPARAM) lpNdsUserName ); } } } pConnInfo = (PCONN_INFORMATION) ( ((BYTE *)pConnInfo) + dwSize ); } } else { *lpdwUserLuid = 0; } } BOOL WINAPI NwpChangePasswdDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This function is the window management message handler for the change password dialog. Arguments: DialogHandle - Supplies a handle to display the dialog. Message - Supplies the window management message. LParam - Supplies the pointer to a buffer which on input contains the Server string under which the user needs to type in a new credential before browsing. On output, this pointer contains the username and server strings entered to the dialog box. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { static LPWSTR UserName; static LPWSTR ServerName; static DWORD UserNameSize ; static DWORD ServerNameSize ; INT Result ; PPASSWDDLGPARAM DlgParams ; switch (Message) { case WM_INITDIALOG: DlgParams = (PPASSWDDLGPARAM) LParam; UserName = DlgParams->UserName ; ServerName = DlgParams->ServerName ; UserNameSize = DlgParams->UserNameSize ; ServerNameSize = DlgParams->ServerNameSize ; // // Position dialog // NwpCenterDialog(DialogHandle); // // setup the default user and server names // SetDlgItemTextW(DialogHandle, ID_SERVER, ServerName); SetDlgItemTextW(DialogHandle, ID_USERNAME, UserName); // // Username is limited to 256 characters. // SendDlgItemMessageW(DialogHandle, ID_USERNAME, EM_LIMITTEXT, UserNameSize - 1, // minus space for '\0' 0 ); // // Server is limited to 256 characters. // SendDlgItemMessageW( DialogHandle, ID_SERVER, EM_LIMITTEXT, ServerNameSize - 1, // minus space for '\0' 0 ); // // Add trees to list // NwpAddToComboBox( DialogHandle, ID_SERVER, NULL, FALSE ) ; return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDOK: Result = GetDlgItemTextW( DialogHandle, ID_USERNAME, UserName, UserNameSize ); Result = GetDlgItemTextW( DialogHandle, ID_SERVER, ServerName, ServerNameSize ); EndDialog(DialogHandle, (INT) IDOK); // OK return TRUE; case IDCANCEL: EndDialog(DialogHandle, (INT) IDCANCEL); // CANCEL return TRUE; } } // // We didn't process this message // return FALSE; } BOOL WINAPI NwpOldPasswordDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) // // This dialog lets the user retype the old password for a specific // server/tree. // { static POLD_PW_DLG_PARAM OldPwParam; switch (Message) { case WM_INITDIALOG: OldPwParam = (POLD_PW_DLG_PARAM) LParam; NwpCenterDialog(DialogHandle); SetDlgItemTextW(DialogHandle, ID_SERVER, OldPwParam->FailedServer); SendDlgItemMessageW( DialogHandle, ID_PASSWORD, EM_LIMITTEXT, NW_MAX_PASSWORD_LEN, 0 ); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDCANCEL: EndDialog(DialogHandle, IDCANCEL); return TRUE; case IDOK: { UCHAR EncodeSeed = NW_ENCODE_SEED2; UNICODE_STRING PasswordStr; RtlZeroMemory( OldPwParam->OldPassword, NW_MAX_PASSWORD_LEN * sizeof(WCHAR) ); GetDlgItemTextW( DialogHandle, ID_PASSWORD, OldPwParam->OldPassword, NW_MAX_PASSWORD_LEN ); #if DBG IF_DEBUG(LOGON) { KdPrint(("NWPROVAU: Retyped password %ws\n", OldPwParam->OldPassword)); } #endif RtlInitUnicodeString(&PasswordStr, OldPwParam->OldPassword); RtlRunEncodeUnicodeString(&EncodeSeed, &PasswordStr); EndDialog(DialogHandle, IDOK); return TRUE; } case IDHELP: DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_OLD_PW_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); return TRUE; default: return FALSE; } } // // We didn't process this message // return FALSE; } BOOL WINAPI NwpAltUserNameDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) // // This dialog lets the user retype an alternate username for a specific // server/tree. // { static PUSERNAME_DLG_PARAM UserNameParam; switch (Message) { case WM_INITDIALOG: UserNameParam = (PUSERNAME_DLG_PARAM) LParam; NwpCenterDialog(DialogHandle); // // Display the server/tree. // SetDlgItemTextW( DialogHandle, ID_SERVER, UserNameParam->TreeServerName ); // // Username is limited to 256 characters. // SendDlgItemMessageW( DialogHandle, ID_USERNAME, EM_LIMITTEXT, 256, 0 ); SetDlgItemTextW( DialogHandle, ID_USERNAME, UserNameParam->UserName ); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDCANCEL: EndDialog(DialogHandle, IDCANCEL); return TRUE; case IDOK: { RtlZeroMemory( UserNameParam->UserName, 256 * sizeof(WCHAR) ); GetDlgItemTextW( DialogHandle, ID_USERNAME, UserNameParam->UserName, 256 ); #if DBG IF_DEBUG(LOGON) { KdPrint(("NWPROVAU: Retyped username %ws\n", UserNameParam->UserName)); } #endif EndDialog(DialogHandle, IDOK); return TRUE; } case IDHELP: DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_ALT_UN_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); return TRUE; default: return FALSE; } } // // We didn't process this message // return FALSE; } VOID EnableAddRemove( IN HWND DialogHandle ) /*++ Routine Description: This function enables and disables Add and Remove buttons based on list box selections. Arguments: DialogHandle - Supplies a handle to the windows dialog. Return Value: None. --*/ { INT cSel; cSel = SendDlgItemMessageW( DialogHandle, ID_INACTIVE_LIST, LB_GETSELCOUNT, 0, 0 ); EnableWindow(GetDlgItem(DialogHandle, ID_ADD), cSel != 0); cSel = SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_GETSELCOUNT, 0, 0 ); EnableWindow(GetDlgItem(DialogHandle, ID_REMOVE), cSel != 0); } BOOL WINAPI NwpSelectServersDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: This routine displays two listboxes--an active list which includes the trees which the user is currently attached to, and an inactive list which displays the rest of the trees on the net. The user can select trees and move them back and forth between the list boxes. When OK is selected, the password is changed on the trees in the active listbox. Arguments: DialogHandle - Supplies a handle to the login dialog. Message - Supplies the window management message. LParam - Supplies the user credential: username, old password and new password. The list of trees from the active listbox and the number of entries are returned. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { WCHAR szServer[NW_MAX_SERVER_LEN + 1]; static PCHANGE_PW_DLG_PARAM Credential; DWORD status; DWORD UserLuid = 0; DWORD ActiveListBoxCount; DWORD InactiveListBoxCount; switch (Message) { case WM_INITDIALOG: // // Get the user credential passed in. // Credential = (PCHANGE_PW_DLG_PARAM) LParam; // // Position dialog // NwpCenterDialog(DialogHandle); // // Display the username. // SetDlgItemTextW( DialogHandle, ID_USERNAME, Credential->UserName ); // // Display current NetWare tree connections in the active box. // NwpAddNetWareTreeConnectionsToList( DialogHandle, Credential->UserName, &UserLuid, ID_ACTIVE_LIST ); // // Display all trees in inactive list box. // NwpAddTreeNamesToControl( DialogHandle, ID_INACTIVE_LIST, LB_ADDSTRING, ID_ACTIVE_LIST, LB_FINDSTRING ); // // Highlight the first entry of the inactive list. // SetFocus(GetDlgItem(DialogHandle, ID_INACTIVE_LIST)); SendDlgItemMessageW( DialogHandle, ID_INACTIVE_LIST, LB_SETSEL, TRUE, 0 ); EnableAddRemove(DialogHandle); ActiveListBoxCount = SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_GETCOUNT, 0, 0 ); InactiveListBoxCount = SendDlgItemMessageW( DialogHandle, ID_INACTIVE_LIST, LB_GETCOUNT, 0, 0 ); if ( ActiveListBoxCount == 0 && InactiveListBoxCount == 0 ) { (void) NwpMessageBoxError( DialogHandle, IDS_NETWARE_TITLE, IDS_NO_TREES_DETECTED, 0, NULL, MB_OK ); EndDialog(DialogHandle, (INT) IDOK); } return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDOK: { if ((status = NwpGetTreesAndChangePw( DialogHandle, szServer, UserLuid, Credential ) != NO_ERROR)) { // // System error: e.g. out of memory error. // (void) NwpMessageBoxError( DialogHandle, IDS_CHANGE_PASSWORD_TITLE, 0, status, NULL, MB_OK | MB_ICONSTOP ); EndDialog(DialogHandle, (INT) -1); return TRUE; } EndDialog(DialogHandle, (INT) IDOK); return TRUE; } case IDCANCEL: EndDialog(DialogHandle, (INT) IDCANCEL); return TRUE; case IDHELP: DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_PW_SELECT_SERVERS_HELP), (HWND) DialogHandle, NwpHelpDlgProc, (LPARAM) 0 ); return TRUE; case ID_ACTIVE_LIST: // // When Remove is pressed the highlights follows // the selected entries over to the other // list box. // if (HIWORD(WParam) == LBN_SELCHANGE) { // // Unselect the other listbox // SendDlgItemMessageW( DialogHandle, ID_INACTIVE_LIST, LB_SETSEL, FALSE, (LPARAM) -1 ); EnableAddRemove(DialogHandle); } return TRUE; case ID_INACTIVE_LIST: // // When Add is pressed the highlights follows // the selected entries over to the other // list box. // if (HIWORD(WParam) == LBN_SELCHANGE) { // // Unselect the other listbox // SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_SETSEL, FALSE, (LPARAM) -1 ); EnableAddRemove(DialogHandle); } return TRUE; case ID_ADD: case ID_REMOVE: { INT idFrom; INT idTo; INT cSel; INT SelItem; INT iNew; HWND hwndActiveList; HWND hwndInactiveList; hwndActiveList = GetDlgItem(DialogHandle, ID_ACTIVE_LIST); hwndInactiveList = GetDlgItem(DialogHandle, ID_INACTIVE_LIST); // // Set to NOREDRAW to TRUE // SetWindowLong(hwndActiveList, GWL_STYLE, GetWindowLong(hwndActiveList, GWL_STYLE) | LBS_NOREDRAW); SetWindowLong(hwndInactiveList, GWL_STYLE, GetWindowLong(hwndInactiveList, GWL_STYLE) | LBS_NOREDRAW); if (LOWORD(WParam) == ID_ADD) { idFrom = ID_INACTIVE_LIST; idTo = ID_ACTIVE_LIST; } else { idFrom = ID_ACTIVE_LIST; idTo = ID_INACTIVE_LIST; } // // Move current selection from idFrom to idTo // // // Loop terminates when selection count is zero // for (;;) { // // Get count of selected strings // cSel = SendDlgItemMessageW( DialogHandle, idFrom, LB_GETSELCOUNT, 0, 0 ); if (cSel == 0) { // // No more selection // break; } // // To avoid flickering as strings are added and // removed from listboxes, no redraw is set for // both listboxes until we are transfering the // last entry, in which case we reenable redraw // so that both listboxes are updated once. // if (cSel == 1) { SetWindowLong( hwndActiveList, GWL_STYLE, GetWindowLong(hwndActiveList, GWL_STYLE) & ~LBS_NOREDRAW ); SetWindowLong( hwndInactiveList, GWL_STYLE, GetWindowLong(hwndInactiveList, GWL_STYLE) & ~LBS_NOREDRAW ); } // // Get index of first selected item // SendDlgItemMessageW( DialogHandle, idFrom, LB_GETSELITEMS, 1, (LPARAM) &SelItem ); // // Get server name from list // SendDlgItemMessageW( DialogHandle, idFrom, LB_GETTEXT, (WPARAM) SelItem, (LPARAM) (LPWSTR) szServer ); // // Remove entry from list // SendDlgItemMessageW( DialogHandle, idFrom, LB_DELETESTRING, (WPARAM) SelItem, 0 ); // // Add entry to list // iNew = SendDlgItemMessageW( DialogHandle, idTo, LB_ADDSTRING, 0, (LPARAM) (LPWSTR) szServer ); // // Select the new item // if (iNew != LB_ERR) { SendDlgItemMessageW( DialogHandle, idTo, LB_SETSEL, TRUE, iNew ); } } // for EnableAddRemove(DialogHandle); } // ID_ADD or ID_REMOVE } } // // We didn't process this message // return FALSE; } DWORD NwpGetTreesAndChangePw( IN HWND DialogHandle, IN LPWSTR ServerBuf, IN DWORD UserLuid, IN PCHANGE_PW_DLG_PARAM Credential ) /*++ Routine Description: This routine gets the selected trees from the active list box and asks the redirector to change password on them. If a failure is encountered when changing password on a tree, we pop up appropriate dialogs to see if user can fix problem. Arguments: DialogHandle - Supplies a handle to the login dialog. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { DWORD status; HCURSOR Cursor; WCHAR tempOldPassword[NW_MAX_PASSWORD_LEN + 1]; WCHAR tempNewPassword[NW_MAX_PASSWORD_LEN + 1]; WCHAR tempUserName[MAX_NDS_NAME_CHARS]; // // Turn cursor into hourglass // Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } Credential->ChangedOne = FALSE; Credential->TreeList = NULL; Credential->UserList = NULL; // // Get the number of trees we have to change password on. // Credential->Entries = SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_GETCOUNT, 0, 0 ); if (Credential->Entries != 0) { DWORD Entries; // Number of entries in remaining list DWORD FullIndex; // Index to the whole tree list DWORD i; DWORD BytesNeeded = sizeof(LPWSTR) * Credential->Entries + (NW_MAX_SERVER_LEN + 1) * sizeof(WCHAR) * Credential->Entries; LPBYTE FixedPortion; LPWSTR EndOfVariableData; INT Result; Entries = Credential->Entries; Credential->TreeList = LocalAlloc(0, BytesNeeded); Credential->UserList = LocalAlloc(0, sizeof(LPWSTR) * Credential->Entries); if (Credential->TreeList == NULL) { KdPrint(("NWPROVAU: No memory to change password\n")); return ERROR_NOT_ENOUGH_MEMORY; } if (Credential->UserList == NULL) { KdPrint(("NWPROVAU: No memory to change password\n")); return ERROR_NOT_ENOUGH_MEMORY; } FixedPortion = (LPBYTE) Credential->TreeList; EndOfVariableData = (LPWSTR) ((DWORD) FixedPortion + ROUND_DOWN_COUNT(BytesNeeded, ALIGN_DWORD)); for (i = 0; i < Entries; i++) { // // Read the user selected list of servers from the dialog. // SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_GETTEXT, (WPARAM) i, (LPARAM) (LPWSTR) ServerBuf ); NwlibCopyStringToBuffer( ServerBuf, wcslen(ServerBuf), (LPCWSTR) FixedPortion, &EndOfVariableData, &(Credential->TreeList)[i] ); Result = SendDlgItemMessageW( DialogHandle, ID_ACTIVE_LIST, LB_GETITEMDATA, (WPARAM) i, 0 ); if ( Result != LB_ERR ) { (Credential->UserList)[i] = (LPWSTR) Result; } else { (Credential->UserList)[i] = NULL; } FixedPortion += sizeof(LPWSTR); } FullIndex = 0; do { RtlZeroMemory( tempUserName, sizeof(tempUserName) ); RtlZeroMemory( tempOldPassword, sizeof(tempOldPassword) ); RtlZeroMemory( tempNewPassword, sizeof(tempNewPassword) ); RtlCopyMemory( tempOldPassword, Credential->OldPassword, sizeof(tempOldPassword) ); RtlCopyMemory( tempNewPassword, Credential->NewPassword, sizeof(tempNewPassword) ); if ( (Credential->UserList)[FullIndex] == NULL ) { // We don't have any connections to tree // Prompt user to supply a user name for which account // we are to change password, or skip . . . USERNAME_DLG_PARAM UserNameParam; CHANGE_PASS_DLG_PARAM ChangePassParam; UserNameParam.UserName = tempUserName; UserNameParam.TreeServerName = (Credential->TreeList)[FullIndex]; SetCursor(Cursor); ShowCursor(FALSE); Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_ALT_USERNAME), (HWND) DialogHandle, NwpAltUserNameDlgProc, (LPARAM) &UserNameParam ); Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } if ( Result != IDOK ) { *((Credential->TreeList)[FullIndex]) = L'\0'; goto SkipEntry; } // Now go reverify the credentials for the user name // entered by user. ChangePassParam.UserName = tempUserName; ChangePassParam.TreeName = (Credential->TreeList)[FullIndex]; ChangePassParam.OldPassword = tempOldPassword; ChangePassParam.NewPassword = tempNewPassword; SetCursor(Cursor); ShowCursor(FALSE); Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD3), (HWND) DialogHandle, NwpChangePasswordDlgProc, (LPARAM) &ChangePassParam ); Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } if ( Result != IDOK ) { *((Credential->TreeList)[FullIndex]) = L'\0'; goto SkipEntry; } goto Next; } else { wcscpy( tempUserName, (Credential->UserList)[FullIndex] ); LocalFree( (Credential->UserList)[FullIndex] ); (Credential->UserList)[FullIndex] = NULL; } // Test tempUserName with the user name in Credential->UserName // to see if they are similar (i.e. The first part of the // NDS distinguish name matches). if ( _wcsnicmp( tempUserName + 3, Credential->UserName, wcslen( Credential->UserName ) ) ) { // The names are not similar! // Prompt user to ask if they really want to change // passwords for dis-similar user on tree // or skip . . . USERNAME_DLG_PARAM UserNameParam; CHANGE_PASS_DLG_PARAM ChangePassParam; UserNameParam.UserName = tempUserName; UserNameParam.TreeServerName = (Credential->TreeList)[FullIndex]; SetCursor(Cursor); ShowCursor(FALSE); Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_ALT_USERNAME), (HWND) DialogHandle, NwpAltUserNameDlgProc, (LPARAM) &UserNameParam ); Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } if ( Result != IDOK ) { *((Credential->TreeList)[FullIndex]) = L'\0'; goto SkipEntry; } // Now go reverify the credentials for the user name // entered by user. ChangePassParam.UserName = tempUserName; ChangePassParam.TreeName = (Credential->TreeList)[FullIndex]; ChangePassParam.OldPassword = tempOldPassword; ChangePassParam.NewPassword = tempNewPassword; SetCursor(Cursor); ShowCursor(FALSE); Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_CHANGE_PASSWORD3), (HWND) DialogHandle, NwpChangePasswordDlgProc, (LPARAM) &ChangePassParam ); Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } if ( Result != IDOK ) { *((Credential->TreeList)[FullIndex]) = L'\0'; goto SkipEntry; } } Next: status = NwrChangePassword( NULL, // Reserved UserLuid, tempUserName, tempOldPassword, // Encoded passwords tempNewPassword, (LPWSTR) (Credential->TreeList)[FullIndex] ); if (status == ERROR_INVALID_PASSWORD) { OLD_PW_DLG_PARAM OldPasswordParam; #if DBG IF_DEBUG(LOGON) { KdPrint(("NWPROVAU: First attempt: wrong password on %ws\n", (Credential->TreeList)[FullIndex])); } #endif // // Display dialog to let user type in an alternate // old password. // // // Set up old password buffer to receive from dialog. // OldPasswordParam.OldPassword = tempOldPassword; OldPasswordParam.FailedServer = (Credential->TreeList)[FullIndex]; SetCursor(Cursor); ShowCursor(FALSE); Result = DialogBoxParamW( hmodNW, MAKEINTRESOURCEW(DLG_ENTER_OLD_PASSWORD), (HWND) DialogHandle, NwpOldPasswordDlgProc, (LPARAM) &OldPasswordParam ); Cursor = LoadCursor(NULL, IDC_WAIT); if (Cursor != NULL) { SetCursor(Cursor); ShowCursor(TRUE); } if (Result == IDOK) { // // Retry change password with alternate old password on // the failed server. // status = NwrChangePassword( NULL, // Reserved UserLuid, tempUserName, tempOldPassword, // Alternate old password tempNewPassword, (LPWSTR) (Credential->TreeList)[FullIndex] ); } } if (status != NO_ERROR) { // // Either unrecoverable failure or user failed to change // password on second attempt. // #if DBG IF_DEBUG(LOGON) { KdPrint(("NWPROVAU: Failed to change password on %ws %lu\n", (Credential->TreeList)[FullIndex], status)); } #endif // Pop up error dialog to let user know that password // could not be changed. (void) NwpMessageBoxError( DialogHandle, IDS_CHANGE_PASSWORD_TITLE, IDS_CP_FAILURE_WARNING, status, (LPWSTR) (Credential->TreeList)[FullIndex], MB_OK | MB_ICONSTOP ); *((Credential->TreeList)[FullIndex]) = L'\0'; if (status == ERROR_NOT_ENOUGH_MEMORY) return status; } SkipEntry: // // Continue to change password on the rest of the entries // FullIndex++; Entries = Credential->Entries - FullIndex; } while (Entries); // // Caller is responsible for freeing TreeList // } SetCursor(Cursor); ShowCursor(FALSE); return NO_ERROR; } BOOL WINAPI NwpChangePasswordSuccessDlgProc( HWND DialogHandle, UINT Message, WPARAM WParam, LPARAM LParam ) /*++ Routine Description: Arguments: DialogHandle - Supplies a handle to the login dialog. Message - Supplies the window management message. Return Value: TRUE - the message was processed. FALSE - the message was not processed. --*/ { static PCHANGE_PW_DLG_PARAM Credential; DWORD Count; DWORD i; switch (Message) { case WM_INITDIALOG: // // Get the user credential passed in. // Credential = (PCHANGE_PW_DLG_PARAM) LParam; // // Position dialog // NwpCenterDialog(DialogHandle); // // Put list of NetWare trees that we changed password on in the // list box. // ID_SERVER ); for ( i = 0; i < Credential->Entries; i++ ) { if ( *((Credential->TreeList)[i]) != L'\0' ) { SendDlgItemMessageW( DialogHandle, ID_SERVER, LB_ADDSTRING, 0, (LPARAM) (Credential->TreeList)[i] ); } } Count = SendDlgItemMessageW( DialogHandle, ID_SERVER, LB_GETCOUNT, 0, 0 ); if ( Count == 0 ) EndDialog(DialogHandle, 0); return TRUE; case WM_COMMAND: switch (LOWORD(WParam)) { case IDOK: case IDCANCEL: EndDialog(DialogHandle, 0); return TRUE; } } // // We didn't process this message // return FALSE; }