Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1799 lines
50 KiB

/*
File usertab.c
Implementation of the users dialog tab for the dialup server ui.
Paul Mayfield, 9/29/97
*/
#include "rassrv.h"
#include "usertab.h"
#include <htmlhelp.h>
#define USERTAB_PASSWORD_BUFFER_SIZE (PWLEN+1)
static const WCHAR pszDummyPassword[] = L"XXXXXXXXXXXXXXX";
// Help maps
static const DWORD phmUserTab[] =
{
CID_UserTab_LV_Users, IDH_UserTab_LV_Users,
CID_UserTab_PB_New, IDH_UserTab_PB_New,
CID_UserTab_PB_Delete, IDH_UserTab_PB_Delete,
CID_UserTab_PB_Properties, IDH_UserTab_PB_Properties,
CID_UserTab_PB_SwitchToMMC, IDH_UserTab_PB_SwitchToMMC,
CID_UserTab_CB_BypassDcc, IDH_UserTab_CB_BypassDcc,
0, 0
};
static const DWORD phmCallback[] =
{
CID_UserTab_Callback_RB_Caller, IDH_UserTab_Callback_RB_Caller,
CID_UserTab_Callback_RB_Admin, IDH_UserTab_Callback_RB_Admin,
CID_UserTab_Callback_EB_Number, IDH_UserTab_Callback_EB_Number,
CID_UserTab_Callback_RB_No, IDH_UserTab_Callback_RB_No,
0, 0
};
static const DWORD phmNewUser[] =
{
CID_UserTab_New_EB_Username, IDH_UserTab_New_EB_Username,
CID_UserTab_New_EB_Fullname, IDH_UserTab_New_EB_Fullname,
CID_UserTab_New_EB_Password1, IDH_UserTab_New_EB_Password1,
CID_UserTab_New_EB_Password2, IDH_UserTab_New_EB_Password2,
0, 0
};
// Parameters to track net users
//
typedef struct _RASSRV_USER_PARAMS
{
BOOL bCanceled; // Set by property sheets when cancel pressed
BOOL bNewUser; // for .Net 691639, the password change warning dialog won't pop up when creating new users. gangz
// General properties
//For whistler bug 210032 to allow username be 20 characters long
WCHAR pszLogonName[IC_USERNAME];
WCHAR pszFullName [IC_USERFULLNAME+1]; // For whistler bug 39081 gangz
WCHAR pszPassword1[USERTAB_PASSWORD_BUFFER_SIZE];
WCHAR pszPassword2[USERTAB_PASSWORD_BUFFER_SIZE];
DWORD dwErrorCode;
// Callback properties
HANDLE hUser;
BOOL bNone;
BOOL bCaller;
BOOL bAdmin;
WCHAR pszNumber[MAX_PHONE_NUMBER_LEN];
} RASSRV_USER_PARAMS;
// Fills in the property sheet structure with the information
// required to display the user database tab.
//
DWORD
UserTabGetPropertyPage(
IN LPPROPSHEETPAGE ppage,
IN LPARAM lpUserData)
{
// Initialize
ZeroMemory(ppage, sizeof(PROPSHEETPAGE));
// Fill in the values
ppage->dwSize = sizeof(PROPSHEETPAGE);
ppage->hInstance = Globals.hInstDll;
ppage->pszTemplate = MAKEINTRESOURCE(PID_UserTab);
ppage->pfnDlgProc = UserTabDialogProc;
ppage->pfnCallback = RasSrvInitDestroyPropSheetCb;
ppage->dwFlags = PSP_USECALLBACK;
ppage->lParam = lpUserData;
return NO_ERROR;
}
//
// Error reporting
//
VOID
UserTabDisplayError(
IN HWND hwnd,
IN DWORD err)
{
ErrDisplayError(
hwnd,
err,
ERR_USERTAB_CATAGORY,
ERR_USERDB_SUBCAT,
Globals.dwErrorData);
}
// Fills in the user list view with the names of the users stored in the
// user database provide. Also, initializes the checked/unchecked status
// of each user.
DWORD
UserTabFillUserList(
IN HWND hwndLV,
IN HANDLE hUserDatabase)
{
LV_ITEM lvi;
DWORD dwCount, i, dwErr, dwSize;
HANDLE hUser;
WCHAR pszName[IC_USERFULLNAME+IC_USERNAME+3];
// char pszAName[512];
HIMAGELIST checks;
BOOL bDialinEnabled;
// Get the count of all the users
if ((dwErr = usrGetUserCount(hUserDatabase, &dwCount)) != NO_ERROR)
{
UserTabDisplayError(hwndLV, ERR_USER_DATABASE_CORRUPT);
return dwErr;
}
ListView_SetUserImageList(hwndLV, Globals.hInstDll);
// Initialize the list item
ZeroMemory(&lvi, sizeof(LV_ITEM));
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
// Looop through all of the users adding their names as we go
for (i=0; i<dwCount; i++)
{
dwSize = sizeof(pszName)/sizeof(pszName[0]); // For whistler bug 39081 gangz
if ((dwErr = usrGetUserHandle(hUserDatabase, i, &hUser)) == NO_ERROR)
{
usrGetDisplayName (hUser, pszName, &dwSize);
usrGetDialin(hUser, &bDialinEnabled);
lvi.iImage = UI_Connections_User;
lvi.iItem = i;
lvi.pszText = pszName;
lvi.cchTextMax = wcslen(pszName)+1;
ListView_InsertItem(hwndLV,&lvi);
ListView_SetCheck(hwndLV, i, bDialinEnabled);
}
}
// Select the first item in the list view
ListView_SetItemState(
hwndLV,
0,
LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED);
return NO_ERROR;
}
//
// Initialize the user tab, returns false if focus was set,
// true otherwise.
//
DWORD
UserTabInitializeDialog(
HWND hwndDlg,
WPARAM wParam,
LPARAM lParam)
{
HANDLE hUserDatabase = NULL;
HWND hwndLV, hwndEnc, hwndBypass;
LV_COLUMN lvc;
RECT r;
DWORD dwErr;
BOOL bPure = FALSE, bBypass = FALSE;
// Obtain handle to user database
RasSrvGetDatabaseHandle(hwndDlg, ID_USER_DATABASE, &hUserDatabase);
// Figure out if MMC has been used.
dwErr = usrIsDatabasePure (hUserDatabase, &bPure);
if ((dwErr == NO_ERROR) && (bPure == FALSE))
{
PWCHAR pszWarning, pszTitle;
pszWarning = (PWCHAR) PszLoadString(
Globals.hInstDll,
WRN_USERS_CONFIGURED_MMC);
pszTitle = (PWCHAR) PszLoadString(
Globals.hInstDll,
ERR_USERTAB_CATAGORY);
MessageBox(hwndDlg, pszWarning, pszTitle, MB_OK | MB_ICONWARNING);
usrSetDatabasePure(hUserDatabase, TRUE);
}
// Fill in the user list if it's not already filled
hwndLV = GetDlgItem(hwndDlg, CID_UserTab_LV_Users);
if (ListView_GetItemCount (hwndLV) == 0)
{
ListView_InstallChecks(hwndLV, Globals.hInstDll);
UserTabFillUserList(hwndLV, hUserDatabase);
// Add a colum so that we'll display in report view
GetClientRect(hwndLV, &r);
lvc.mask = LVCF_FMT;
lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(hwndLV,0,&lvc);
ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER);
// Initialize the encryption check box
// For .Net 554416, removed the Require Encryption check box
// For security, the default is require secured password and encrytpion
// now
// Initialize the "bypass dcc" checkbox
hwndBypass = GetDlgItem(hwndDlg, CID_UserTab_CB_BypassDcc);
if (hwndBypass != NULL)
{
usrGetDccBypass(hUserDatabase, &bBypass);
SendMessage(
hwndBypass,
BM_SETCHECK,
(bBypass) ? BST_CHECKED : BST_UNCHECKED,
0);
}
}
return TRUE;
}
//
// Cleanup anything done in the initialization function
//
DWORD
UserTabCleanupDialog(
IN HWND hwndDlg,
IN WPARAM wParam,
IN LPARAM lParam)
{
// Restore the user data
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
return NO_ERROR;
}
//
// Grants/revokes the dialin privelege of a user and reflects this
// in the UI
//
DWORD
UserTabHandleUserCheck(
IN HWND hwndDlg,
IN DWORD dwIndex)
{
DWORD dwErr;
HANDLE hUser = NULL, hUserDatabase = NULL;
HWND hwndLV = GetDlgItem(hwndDlg, CID_UserTab_LV_Users);
// Get the user handle from the user database
RasSrvGetDatabaseHandle(hwndDlg, ID_USER_DATABASE, &hUserDatabase);
dwErr = usrGetUserHandle(hUserDatabase, dwIndex, &hUser);
if (dwErr != NO_ERROR)
{
UserTabDisplayError(hwndDlg, ERR_USER_DATABASE_CORRUPT);
return dwErr;
}
if (hwndLV)
{
// Set the dialin permission of the given user
usrEnableDialin(hUser, ListView_GetCheck(hwndLV, dwIndex));
}
return NO_ERROR;
}
// .Net 660285
// Add password change warning dialogbox
// Because the resource files are all locked down, I have to borrow
// the resource localsec.dll for .Net and XPSP
//
// In longhorn, I will create our own resource file
//
BOOL
PwInit(
IN HWND hwndDlg )
{
PWCHAR pszTitle = NULL;
pszTitle = (PWCHAR) PszLoadString (
Globals.hInstDll,
WRN_TITLE);
SetWindowTextW (hwndDlg, pszTitle);
return FALSE;
}
BOOL
PwCommand(
IN HWND hwnd,
IN WORD wNotification,
IN WORD wId,
IN HWND hwndCtrl )
{
DWORD dwErr;
switch (wId)
{
case IDC_HELP_BUTTON:
{
HtmlHelp(
hwnd,
TEXT("password.chm::/datalos.htm"),
HH_DISPLAY_TOPIC,
0);
break;
}
case IDOK:
case IDCANCEL:
{
EndDialog( hwnd, (wId == IDOK) );
return TRUE;
}
}
return FALSE;
}
INT_PTR CALLBACK
PwDlgProc(
IN HWND hwnd,
IN UINT unMsg,
IN WPARAM wparam,
IN LPARAM lparam )
{
switch (unMsg)
{
case WM_INITDIALOG:
{
return PwInit( hwnd );
}
case WM_COMMAND:
{
return PwCommand(
hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
}
}
return FALSE;
}
DWORD WarnPasswordChange(
IN BOOL * pfChange )
{
HMODULE hModule = NULL;
DWORD dwErr = NO_ERROR;
INT_PTR nStatus;
do
{
if( NULL == pfChange )
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
*pfChange = FALSE;
hModule = LoadLibrary(TEXT("LocalSec.dll"));
if ( NULL == hModule )
{
dwErr = GetLastError();
break;
}
// Look up the IDD_SET_PASSWORD_WARNING_OTHER_FRIENDLY resource
// whose id values is 5174 in the localsec.dll
//
nStatus =
(BOOL )DialogBox(
hModule,
MAKEINTRESOURCE(IDD_SET_PASSWORD_WARNING_OTHER_FRIENDLY),
NULL,
PwDlgProc);
if (nStatus == -1)
{
dwErr = GetLastError();
break;
}
*pfChange = (BOOL )nStatus;
}
while(FALSE);
if( NULL != hModule )
{
FreeLibrary( hModule );
}
return dwErr;
}
//
// Loads the New User parameters and returns whether they
// have been correctly entered or not.
//
//Assume passwords in the input params are already encoded
BOOL
UserTabNewUserParamsOk(
IN HWND hwndDlg,
IN RASSRV_USER_PARAMS * pNuParams)
{
USER_MODALS_INFO_0 * pModInfo;
NET_API_STATUS nStatus;
DWORD dwMinPasswordLength=0, dwLength;
BOOL bOk = FALSE;
HWND hwndControl = NULL;
// Find the minium password length
nStatus = NetUserModalsGet(NULL, 0, (LPBYTE*)&pModInfo);
if (nStatus == NERR_Success)
{
dwMinPasswordLength = pModInfo->usrmod0_min_passwd_len;
NetApiBufferFree((LPBYTE)pModInfo);
}
// Load the parameters
hwndControl = GetDlgItem(hwndDlg, CID_UserTab_New_EB_Username);
if (hwndControl)
{
GetWindowTextW(
hwndControl,
pNuParams->pszLogonName,
(sizeof(pNuParams->pszLogonName)/sizeof(WCHAR)) - 1);
}
hwndControl = GetDlgItem(hwndDlg, CID_UserTab_New_EB_Fullname);
if (hwndControl)
{
GetWindowTextW(
hwndControl,
pNuParams->pszFullName,
(sizeof(pNuParams->pszFullName)/sizeof(WCHAR)) - 1);
}
hwndControl = GetDlgItem(hwndDlg, CID_UserTab_New_EB_Password1);
//gangz
//For secure password bug .Net 754400
SafeWipePasswordBuf(pNuParams->pszPassword1 );
SafeWipePasswordBuf(pNuParams->pszPassword2 );
if (hwndControl)
{
GetWindowTextW(
hwndControl,
pNuParams->pszPassword1,
(sizeof(pNuParams->pszPassword1)/sizeof(WCHAR)) - 1);
}
hwndControl = GetDlgItem(hwndDlg, CID_UserTab_New_EB_Password2);
if (hwndControl)
{
GetWindowTextW(
hwndControl,
pNuParams->pszPassword2,
(sizeof(pNuParams->pszPassword2)/sizeof(WCHAR)) - 1);
}
do
{
bOk = TRUE;
// Verify that we have a login name
dwLength = wcslen(pNuParams->pszLogonName);
if (dwLength < 1)
{
pNuParams->dwErrorCode = ERR_LOGON_NAME_TOO_SMALL;
bOk = FALSE;
break;
}
// Verify the minimum password length
dwLength = wcslen(pNuParams->pszPassword1);
if (dwLength < dwMinPasswordLength)
{
pNuParams->dwErrorCode = ERR_PASSWORD_TOO_SMALL;
bOk = FALSE;
break;
}
// Verify the passwords was entered correctly
if (wcscmp(pNuParams->pszPassword1, pNuParams->pszPassword2))
{
pNuParams->dwErrorCode = ERR_PASSWORD_MISMATCH;
bOk = FALSE;
break;
}
// For .Net 660285
// Give warning if the password has been changed
// for .Net 691639, the password change warning dialog won't pop up when creating new users. gangz
//
if ( !pNuParams->bNewUser &&
wcscmp(pszDummyPassword, pNuParams->pszPassword1) )
{
BOOL fChange = FALSE;
DWORD dwErr = NO_ERROR;
dwErr = WarnPasswordChange( &fChange );
if( NO_ERROR != dwErr )
{
break;
}
bOk = fChange;
if( !bOk )
{
pNuParams->dwErrorCode = ERROR_CAN_NOT_COMPLETE;
}
}
} while (FALSE);
// Cleanup
{
if (!bOk)
{
//reset password buffer so that other know password is not set yet.
//
SafeWipePasswordBuf(
pNuParams->pszPassword1);
SafeWipePasswordBuf(
pNuParams->pszPassword2);
}
}
// Keep the password field in encrypted status to be logic safe
// Even it is wiped out
SafeEncodePasswordBuf( pNuParams->pszPassword1 );
SafeEncodePasswordBuf( pNuParams->pszPassword2 );
return bOk;
}
//
// Initialize the callback properties of the given user
//
//Passwords are encrypted when passing in
DWORD
UserTabLoadUserProps (
IN RASSRV_USER_PARAMS * pParams)
{
PWCHAR pszName;
DWORD dwErr, dwSize;
PWCHAR pszNumber;
if (!pParams)
{
return ERROR_INVALID_PARAMETER;
}
// If this is a new user, default to user specified callback
// (convienience mode)
if (!pParams->hUser)
{
SafeWipePasswordBuf( pParams->pszPassword1);
SafeWipePasswordBuf( pParams->pszPassword2);
ZeroMemory(pParams, sizeof(*pParams));
SafeEncodePasswordBuf( pParams->pszPassword1);
SafeEncodePasswordBuf( pParams->pszPassword2);
pParams->bNone = TRUE;
pParams->bCaller = FALSE;
pParams->bAdmin = FALSE;
}
// Otherwise, load the user parameters from the user database
else
{
pParams->bCanceled = FALSE;
dwSize = sizeof(pParams->pszFullName)/sizeof(pParams->pszFullName[0]);
usrGetFullName (pParams->hUser, pParams->pszFullName, &dwSize);
usrGetName(pParams->hUser, &pszName);
lstrcpynW(
pParams->pszLogonName,
pszName,
sizeof(pParams->pszLogonName) / sizeof(WCHAR));
SafeWipePasswordBuf( pParams->pszPassword1);
SafeWipePasswordBuf( pParams->pszPassword2);
lstrcpynW(
pParams->pszPassword1,
pszDummyPassword,
sizeof(pParams->pszPassword1) / sizeof(WCHAR));
lstrcpynW(
pParams->pszPassword2,
pszDummyPassword,
sizeof(pParams->pszPassword2) / sizeof(WCHAR));
SafeEncodePasswordBuf( pParams->pszPassword1);
SafeEncodePasswordBuf( pParams->pszPassword2);
dwErr = usrGetCallback(
pParams->hUser,
&pParams->bAdmin,
&pParams->bCaller);
if (dwErr != NO_ERROR)
{
return dwErr;
}
dwErr = usrGetCallbackNumber(pParams->hUser, &pszNumber);
if (dwErr != NO_ERROR)
{
return dwErr;
}
lstrcpynW(
pParams->pszNumber,
pszNumber,
sizeof(pParams->pszNumber) / sizeof(WCHAR));
}
return NO_ERROR;
}
//
// Commit the call back properties of the given user.
//
DWORD
UserTabSaveCallbackProps (
IN RASSRV_USER_PARAMS * pParams)
{
if (!pParams)
{
return ERROR_INVALID_PARAMETER;
}
// If we have a valid handle to the user, set his/her
// properties
if (pParams->hUser)
{
pParams->bNone =
(pParams->bCaller == FALSE && pParams->bAdmin == FALSE);
// Set the enabling and number
usrEnableCallback(
pParams->hUser,
pParams->bNone,
pParams->bCaller,
pParams->bAdmin);
if (pParams->bAdmin)
{
usrSetCallbackNumber(pParams->hUser, pParams->pszNumber);
}
}
return NO_ERROR;
}
// Commit the parameters of the given user. If pOrig is non-null, then all
// fields of pParams will be compare against pOrig and only those that have changed
// will be committed. (optimization)
//
//passwords in the input structure are encoded
DWORD
UserTabSaveUserProps (
IN RASSRV_USER_PARAMS * pParams,
IN RASSRV_USER_PARAMS * pOrig,
IN PBOOL pbChanged)
{
if (!pParams || !pOrig || !pbChanged)
{
return ERROR_INVALID_PARAMETER;
}
*pbChanged = FALSE;
// Commit the full name if changed
if (wcscmp(pParams->pszFullName, pOrig->pszFullName))
{
usrSetFullName(pParams->hUser, pParams->pszFullName);
*pbChanged = TRUE;
}
// Commit the password if changed
SafeDecodePasswordBuf(pParams->pszPassword1);
if (wcscmp(pParams->pszPassword1, pszDummyPassword))
{
usrSetPassword(pParams->hUser, pParams->pszPassword1);
}
SafeEncodePasswordBuf(pParams->pszPassword1);
UserTabSaveCallbackProps(pParams);
return NO_ERROR;
}
DWORD
UserTabCallbackApply(
IN HWND hwndDlg)
{
RASSRV_USER_PARAMS * pParams = NULL;
LONG dwResult = PSNRET_NOERROR;
HWND hwndControl = NULL;
pParams = (RASSRV_USER_PARAMS *)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_No);
if (hwndControl)
{
pParams->bNone = (BOOL)
SendMessage(
hwndControl,
BM_GETCHECK,
0,
0);
}
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_Caller);
if (hwndControl)
{
pParams->bCaller = (BOOL)
SendMessage(
hwndControl,
BM_GETCHECK,
0,
0);
}
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_Admin);
if (hwndControl)
{
pParams->bAdmin = (BOOL)
SendMessage(
hwndControl,
BM_GETCHECK,
0,
0);
}
if (pParams->bAdmin)
{
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_EB_Number);
if (hwndControl)
{
GetWindowTextW(
hwndControl,
pParams->pszNumber,
MAX_PHONE_NUMBER_LEN);
}
// If admin callback was set, but no admin callback number was set,
// then popup an error and don't to refuse the apply
//
if (wcslen(pParams->pszNumber) == 0)
{
UserTabDisplayError(hwndDlg, ERR_CALLBACK_NUM_REQUIRED);
PropSheet_SetCurSel ( GetParent(hwndDlg), hwndDlg, 0 );
dwResult = PSNRET_INVALID;
}
}
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, dwResult);
return TRUE;
}
//
// Dialog procedure that implements getting callback properties
//
INT_PTR
CALLBACK
UserTabCallbackDialogProc(
IN HWND hwndDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PWCHAR lpzNumber, lpzName;
HWND hwndControl = NULL;
HWND hwCb = GetDlgItem(hwndDlg, CID_UserTab_Callback_EB_Number);
RASSRV_USER_PARAMS * pu =
(RASSRV_USER_PARAMS *)(((PROPSHEETPAGE*)lParam)->lParam);
// Initialize
if (hwCb)
{
SendMessage(
hwCb,
EM_SETLIMITTEXT,
sizeof(pu->pszNumber)/2 - 1, 0);
}
SetWindowLongPtr(
hwndDlg,
GWLP_USERDATA,
(LONG_PTR)pu);
// Display the callback properties
if (!pu->bAdmin && !pu->bCaller)
{
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_No);
if (hwndControl)
{
SendMessage(
hwndControl,
BM_SETCHECK,BST_CHECKED,
0);
SetFocus(
hwndControl);
}
}
else if (pu->bCaller)
{
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_Caller);
if (hwndControl)
{
SendMessage(
hwndControl,
BM_SETCHECK,BST_CHECKED,
0);
SetFocus(
hwndControl);
}
}
else
{
hwndControl = GetDlgItem(hwndDlg,CID_UserTab_Callback_RB_Admin);
if (hwndControl)
{
SendMessage(
hwndControl,
BM_SETCHECK,BST_CHECKED,
0);
SetFocus(
hwndControl);
}
}
SetWindowTextW(hwCb, pu->pszNumber);
EnableWindow(hwCb, !!pu->bAdmin);
}
return TRUE;
case WM_HELP:
case WM_CONTEXTMENU:
{
RasSrvHelp (hwndDlg, uMsg, wParam, lParam, phmCallback);
break;
}
case WM_DESTROY:
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
break;
case WM_NOTIFY:
{
NMHDR* pNotifyData;
NM_LISTVIEW* pLvNotifyData;
pNotifyData = (NMHDR*)lParam;
switch (pNotifyData->code)
{
// The property sheet apply button was pressed
case PSN_APPLY:
return UserTabCallbackApply(hwndDlg);
break;
// The property sheet cancel was pressed
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
}
}
break;
case WM_COMMAND:
switch (wParam)
{
case CID_UserTab_Callback_RB_No:
case CID_UserTab_Callback_RB_Caller:
case CID_UserTab_Callback_RB_Admin:
{
HWND hwndNumber = NULL;
HWND hwndAdmin = NULL;
hwndNumber =
GetDlgItem(hwndDlg, CID_UserTab_Callback_EB_Number);
hwndAdmin =
GetDlgItem(hwndDlg, CID_UserTab_Callback_RB_Admin);
if (hwndNumber && hwndAdmin)
{
EnableWindow(
hwndNumber,
(BOOL) SendMessage(
hwndAdmin,
BM_GETCHECK,
0,
0));
}
}
break;
}
break;
}
return FALSE;
}
//
// Initializes the user properties dialog procedure.
//
// Return TRUE if focus is set, false otherwise.
//
BOOL
UserTabInitUserPropsDlg(
IN HWND hwndDlg,
IN WPARAM wParam,
IN LPARAM lParam)
{
HWND hwLogon, hwFull, hwPass1, hwPass2, hwOk, hwCancel;
RASSRV_USER_PARAMS * pu =
(RASSRV_USER_PARAMS *)(((PROPSHEETPAGE*)lParam)->lParam);
hwLogon = GetDlgItem(
hwndDlg,
CID_UserTab_New_EB_Username);
hwFull = GetDlgItem(
hwndDlg,
CID_UserTab_New_EB_Fullname);
hwPass1 = GetDlgItem(
hwndDlg,
CID_UserTab_New_EB_Password1);
hwPass2 = GetDlgItem(
hwndDlg,
CID_UserTab_New_EB_Password2);
hwOk = GetDlgItem(
hwndDlg,
IDOK);
hwCancel = GetDlgItem(
hwndDlg,
IDCANCEL);
// Store the parameters with the window handle
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)pu);
// Set limits to the text that can be entered
if (hwLogon)
{
SendMessage(
hwLogon,
EM_SETLIMITTEXT,
sizeof(pu->pszLogonName)/2 - 2,
0);
SetWindowTextW(hwLogon, pu->pszLogonName);
}
if (hwFull)
{
SendMessage(
hwFull,
EM_SETLIMITTEXT,
sizeof(pu->pszFullName)/2 - 2,
0);
SetWindowTextW(hwFull, pu->pszFullName);
}
if (hwPass1)
{
SendMessage(
hwPass1,
EM_SETLIMITTEXT,
sizeof(pu->pszPassword1)/2 - 2 ,
0);
SafeDecodePasswordBuf(pu->pszPassword1);
SetWindowTextW(hwPass1, pu->pszPassword1);
SafeEncodePasswordBuf(pu->pszPassword1);
}
if (hwPass2)
{
SendMessage(
hwPass2,
EM_SETLIMITTEXT,
sizeof(pu->pszPassword2)/2 - 2,
0);
SafeDecodePasswordBuf(pu->pszPassword2);
SetWindowTextW(hwPass2, pu->pszPassword2);
SafeEncodePasswordBuf(pu->pszPassword2);
}
// Don't allow editing of the logon name if user already exists
// Also, don't show the ok and cancel buttons if the user already
// exits (because it's a property sheet with its own buttons)
if (pu->hUser) {
if (hwLogon)
{
EnableWindow(hwLogon, FALSE);
}
if (hwOk)
{
ShowWindow(hwOk, SW_HIDE);
}
if (hwCancel)
{
ShowWindow(hwCancel, SW_HIDE);
}
}
// Otherwise, we are creating a new user. Change the window
// title to other than "General". Also disable the ok button
// since it will be enabled when a user name is typed in.
else {
PWCHAR pszTitle;
pszTitle = (PWCHAR) PszLoadString (
Globals.hInstDll,
SID_NEWUSER);
SetWindowTextW (hwndDlg, pszTitle);
EnableWindow(hwOk, FALSE);
}
return FALSE;
}
// Dialog procedure that implements the new user
INT_PTR
CALLBACK
UserTabGenUserPropsDlgProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
return UserTabInitUserPropsDlg(hwndDlg, wParam, lParam);
break;
case WM_HELP:
case WM_CONTEXTMENU:
{
RasSrvHelp (hwndDlg, uMsg, wParam, lParam, phmNewUser);
break;
}
case WM_DESTROY:
// Cleanup the work done at WM_INITDIALOG
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
break;
case WM_NOTIFY:
{
NMHDR* pNotifyData;
NM_LISTVIEW* pLvNotifyData;
pNotifyData = (NMHDR*)lParam;
switch (pNotifyData->code) {
// The property sheet apply button was pressed
case PSN_APPLY:
{
RASSRV_USER_PARAMS * pParams;
pParams = (RASSRV_USER_PARAMS *)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (UserTabNewUserParamsOk(hwndDlg, pParams))
{
SetWindowLongPtr(
hwndDlg,
DWLP_MSGRESULT,
PSNRET_NOERROR);
}
else
{
if( ERROR_CAN_NOT_COMPLETE != pParams->dwErrorCode )
{
ErrDisplayError(
hwndDlg,
pParams->dwErrorCode,
ERR_USERTAB_CATAGORY,ERR_USERDB_SUBCAT,
0);
}
SetWindowLongPtr(
hwndDlg,
DWLP_MSGRESULT,
PSNRET_INVALID_NOCHANGEPAGE);
}
}
return TRUE;
// The property sheet cancel was pressed
case PSN_RESET:
{
RASSRV_USER_PARAMS * pParams;
pParams = (RASSRV_USER_PARAMS *)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
pParams->bCanceled = TRUE;
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
}
}
}
break;
case WM_COMMAND:
// Handle ok being pressed
//
if (wParam == IDOK)
{
RASSRV_USER_PARAMS * pParams;
pParams = (RASSRV_USER_PARAMS *)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (UserTabNewUserParamsOk(hwndDlg, pParams))
{
EndDialog(hwndDlg, 1);
}
else
{
if( ERROR_CAN_NOT_COMPLETE != pParams->dwErrorCode )
{
ErrDisplayError(
hwndDlg,
pParams->dwErrorCode,
ERR_USERTAB_CATAGORY,ERR_USERDB_SUBCAT,
0);
}
}
}
// And cancel being pressed
else if (wParam == IDCANCEL)
{
EndDialog(hwndDlg, 0);
}
// Notice whether the user name has been updated and
// if so enable/disable the "Ok" button according to
// whether a name has been entered.
if (HIWORD(wParam) == EN_UPDATE)
{
WCHAR pszName[256];
HWND hwndName;
BOOL bEnable = FALSE;
if (CID_UserTab_New_EB_Username == LOWORD(wParam))
{
// Get the current name
hwndName = (HWND)lParam;
pszName[0] = (WCHAR)0;
GetWindowTextW(
hwndName,
pszName,
sizeof(pszName)/sizeof(WCHAR));
// If the length is greater than 1, enable the
// ok button. Otherwise, disable it.
bEnable = pszName[0] != (WCHAR)0;
EnableWindow(GetDlgItem(hwndDlg, IDOK), bEnable);
}
}
break;
}
return FALSE;
}
// Brings up the new user/properties property sheet.
//
// If bNewUser is set, this is a new user, otherwise pUserParams
// contains the pertanent user information.
//
// Returns:
// NO_ERROR on success, pUserParams will be filled in
// ERROR_CANCELLED if cancel was pressed
// win32 error otherwise
//
// the password in pUserParams are assumed to be encoded
DWORD
UserTabRaiseProperties (
IN HWND hwndParent,
IN RASSRV_USER_PARAMS * pUserParams)
{
PROPSHEETPAGE Pages[2];
PROPSHEETHEADER Header;
INT_PTR ret;
if (!pUserParams)
return ERROR_INVALID_PARAMETER;
// Initialize
// For whistler 524777
ZeroMemory(Pages, sizeof(Pages));
ZeroMemory(&Header, sizeof(Header));
// Fill in the values for the general tab
Pages[0].dwSize = sizeof(PROPSHEETPAGE);
Pages[0].hInstance = Globals.hInstDll;
Pages[0].pszTemplate = MAKEINTRESOURCE(DID_UserTab_New);
Pages[0].pfnDlgProc = UserTabGenUserPropsDlgProc;
Pages[0].pfnCallback = NULL;
Pages[0].dwFlags = 0;
Pages[0].lParam = (LPARAM)pUserParams;
// Fill in the values for the callback tab
Pages[1].dwSize = sizeof(PROPSHEETPAGE);
Pages[1].hInstance = Globals.hInstDll;
Pages[1].pszTemplate = MAKEINTRESOURCE(DID_UserTab_Callback);
Pages[1].pfnDlgProc = UserTabCallbackDialogProc;
Pages[1].pfnCallback = NULL;
Pages[1].dwFlags = 0;
Pages[1].lParam = (LPARAM)pUserParams;
// Fill in the values for the header
Header.dwSize = sizeof(Header);
Header.dwFlags = PSH_DEFAULT |
PSH_PROPSHEETPAGE |
PSH_PROPTITLE |
PSH_NOAPPLYNOW;
Header.hwndParent = hwndParent;
Header.hInstance = Globals.hInstDll;
Header.pszCaption = (pUserParams->hUser) ?
pUserParams->pszLogonName :
pUserParams->pszFullName;
Header.nPages = sizeof(Pages) / sizeof(Pages[0]);
Header.ppsp = Pages;
// Popup the dialog box
if ((ret = PropertySheet(&Header)) == -1)
{
return GetLastError();
}
if (pUserParams->bCanceled)
{
return ERROR_CANCELLED;
}
return NO_ERROR;
}
//
// Raises the new user dialog
//
DWORD
UserTabRaiseNewUserDialog(
IN HWND hwndDlg,
IN RASSRV_USER_PARAMS * pParams)
{
PROPSHEETPAGE Pages;
INT_PTR iRet = 0;
if (!pParams)
{
return ERROR_INVALID_PARAMETER;
}
// Initialize
ZeroMemory(&Pages, sizeof(Pages));
Pages.lParam = (LPARAM)pParams;
// Raise the dialog
iRet = DialogBoxParam(
Globals.hInstDll,
MAKEINTRESOURCE(DID_UserTab_New),
hwndDlg,
UserTabGenUserPropsDlgProc,
(LPARAM)&Pages);
if (iRet == -1)
{
return GetLastError();
}
if (iRet == 0)
{
return ERROR_CANCELLED;
}
return NO_ERROR;
}
//
// Handles a request to add a new user
//
DWORD
UserTabHandleNewUserRequest(
IN HWND hwndDlg)
{
RASSRV_USER_PARAMS Params;
DWORD dwErr = NO_ERROR, dwLength;
HANDLE hUserDatabase = NULL;
HWND hwndLV;
//Encode the password area before leave the password buffer alone
//and any future error return after this should goto directly to :done
SafeEncodePasswordBuf(Params.pszPassword1);
SafeEncodePasswordBuf(Params.pszPassword2);
// Initializes the callback properties
Params.hUser = NULL;
//Password filds are encrypted when passing in and are encrypted when function return
UserTabLoadUserProps (&Params);
// Show the new user property sheet
Params.bNewUser = TRUE; // For .Net 691639, won't raise password change warning dialog when creating new users
dwErr = UserTabRaiseNewUserDialog(hwndDlg, &Params);
if (dwErr != NO_ERROR)
{
goto done;
}
// Flush any changes to the local user database. These can be
// rolled back later with usrRollbackLocalDatabase
RasSrvGetDatabaseHandle(hwndDlg, ID_USER_DATABASE, &hUserDatabase);
SafeDecodePasswordBuf(Params.pszPassword1);
// Make sure you can add the user
dwErr = RasSrvAddUser (
Params.pszLogonName,
Params.pszFullName,
Params.pszPassword1);
SafeEncodePasswordBuf(Params.pszPassword1);
// Figure out whether the user was added successfully
if (dwErr != NO_ERROR)
{
switch (dwErr) {
case ERROR_ACCESS_DENIED:
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_ACCESS);
break;
case ERROR_USER_EXISTS:
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_DUPLICATE);
break;
case ERROR_INVALID_PASSWORDNAME:
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_PASSWORD);
break;
default:
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_GENERIC);
}
goto done;
}
// Delete the user (since he/she will be added later when the database
// is flushed
RasSrvDeleteUser(Params.pszLogonName);
// Add the user to the database
dwErr = usrAddUser(hUserDatabase, Params.pszLogonName, &(Params.hUser));
if (dwErr == ERROR_ALREADY_EXISTS)
{
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_DUPLICATE);
goto done;
}
if (dwErr != NO_ERROR)
{
UserTabDisplayError(hwndDlg, ERR_CANT_ADD_USER_GENERIC);
goto done;
}
// Commit the parameters of this user
if (wcslen(Params.pszFullName) > 0)
{
usrSetFullName (Params.hUser, Params.pszFullName);
}
SafeDecodePasswordBuf(Params.pszPassword1);
dwLength = wcslen(Params.pszPassword1);
if (dwLength > 0)
{
usrSetPassword (Params.hUser, Params.pszPassword1);
}
SafeEncodePasswordBuf(Params.pszPassword1);
UserTabSaveCallbackProps (&Params);
// Delete all of the old items from the list view
hwndLV = GetDlgItem(hwndDlg, CID_UserTab_LV_Users);
if (hwndLV)
{
if (!ListView_DeleteAllItems(hwndLV))
{
UserTabDisplayError(hwndDlg, ERR_GENERIC_CODE);
dwErr = ERR_GENERIC_CODE;
goto done;
}
// Finally, restock the list view
UserTabFillUserList(hwndLV, hUserDatabase);
}
done:
SafeWipePasswordBuf(Params.pszPassword1);
SafeWipePasswordBuf(Params.pszPassword2);
return dwErr;
}
DWORD
UserTabHandleProperties(
IN HWND hwndDlg,
IN DWORD dwIndex)
{
HANDLE hUser = NULL, hUserDatabase = NULL;
RASSRV_USER_PARAMS Params, Orig;
DWORD dwErr = NO_ERROR;
BOOL bNameChanged;
SafeEncodePasswordBuf(Params.pszPassword1);
SafeEncodePasswordBuf(Params.pszPassword2);
// Get a handle to the user in question
RasSrvGetDatabaseHandle(hwndDlg, ID_USER_DATABASE, &hUserDatabase);
dwErr = usrGetUserHandle (hUserDatabase, dwIndex, &hUser);
if (dwErr != NO_ERROR)
{
UserTabDisplayError(hwndDlg, ERR_USER_DATABASE_CORRUPT);
goto done;
}
// Initializes the callback properties
Params.hUser = hUser;
//UserTabLoadUserProps() assume the input password is encoded and will return
// the password encoded.
if ((dwErr = UserTabLoadUserProps (&Params)) != NO_ERROR)
{
goto done;
}
SafeDecodePasswordBuf(Params.pszPassword1);
SafeDecodePasswordBuf(Params.pszPassword2);
CopyMemory( &Orig, &Params, sizeof(Params) );
SafeEncodePasswordBuf(Params.pszPassword1);
SafeEncodePasswordBuf(Params.pszPassword2);
SafeEncodePasswordBuf(Orig.pszPassword1);
SafeEncodePasswordBuf(Orig.pszPassword2);
// Show the user property sheet
Params.bNewUser = FALSE; // for .Net 691639
//Passwords in the Params are already encoded, functions inside
//UserTabRaiseProperties will assume it that way
if ((dwErr = UserTabRaiseProperties(hwndDlg, &Params)) != NO_ERROR)
{
goto done;
}
// Commit any changes needed
// passwords in the input param structures are already encoded
// and will remain encoded when return.
UserTabSaveUserProps(&Params, &Orig, &bNameChanged);
// If the name changed, update the list view
if (bNameChanged)
{
LV_ITEM lvi;
// the 3 is for the '(' ')' and ' '
// like foo (foo)
//
WCHAR pszDispName[IC_USERFULLNAME+IC_USERNAME+3];
DWORD dwSize = sizeof(pszDispName)/sizeof(pszDispName[0]);
HWND hwndLV = GetDlgItem(hwndDlg, CID_UserTab_LV_Users);
// Initialize the list item
ZeroMemory(&lvi, sizeof(LV_ITEM));
lvi.mask = LVIF_TEXT;
lvi.iItem = dwIndex;
lvi.pszText = pszDispName;
usrGetDisplayName(hUser, pszDispName, &dwSize);
if (hwndLV)
{
ListView_SetItem(hwndLV, &lvi);
ListView_RedrawItems(hwndLV, dwIndex, dwIndex);
}
}
done:
SafeWipePasswordBuf(Params.pszPassword1);
SafeWipePasswordBuf(Params.pszPassword2);
SafeWipePasswordBuf(Orig.pszPassword1);
SafeWipePasswordBuf(Orig.pszPassword2);
return NO_ERROR;
}
//
// Handles the request to delete the user at index dwIndex
//
DWORD
UserTabHandleDeleteUser(
IN HWND hwndDlg,
IN DWORD dwIndex)
{
WCHAR *pszCapString, pszCaption[512];
WCHAR *pszTitle, *pszName, pszFullName[IC_USERFULLNAME];
HANDLE hUserDatabase = NULL, hUser = NULL;
DWORD dwErr= NO_ERROR, dwSize = sizeof(pszFullName)/sizeof(pszFullName[0]);
HWND hwndLV = NULL;
INT iRet;
// Get a handle to the user in question
RasSrvGetDatabaseHandle(hwndDlg, ID_USER_DATABASE, &hUserDatabase);
dwErr = usrGetUserHandle (hUserDatabase, dwIndex, &hUser);
if (dwErr != NO_ERROR)
{
UserTabDisplayError(hwndDlg, ERR_USER_DATABASE_CORRUPT);
return dwErr;
}
if ((dwErr = usrGetName(hUser, &pszName)) != NO_ERROR)
{
return dwErr;
}
if ((dwErr = usrGetFullName(hUser, pszFullName, &dwSize)) != NO_ERROR)
{
return dwErr;
}
// Load resources
pszCapString =
(PWCHAR) PszLoadString (Globals.hInstDll, WRN_DELETE_USER_PERMANENT);
pszTitle =
(PWCHAR) PszLoadString (Globals.hInstDll, WRN_TITLE);
// Format the caption
if (wcslen(pszFullName))
wsprintfW(pszCaption, pszCapString, pszFullName);
else
wsprintfW(pszCaption, pszCapString, pszName);
// Advertise the warning
iRet = MessageBox(
hwndDlg,
pszCaption,
pszTitle,
MB_YESNO | MB_ICONWARNING);
if (iRet == IDNO)
{
return NO_ERROR;
}
// Delete the user
if ((dwErr = usrDeleteUser(hUserDatabase, dwIndex)) != NO_ERROR)
{
UserTabDisplayError(hwndDlg, ERR_CANT_DELETE_USER_GENERAL);
return dwErr;
}
// Remove all items from the list view
hwndLV = GetDlgItem(hwndDlg, CID_UserTab_LV_Users);
if (hwndLV)
{
if (!ListView_DeleteAllItems(hwndLV))
{
UserTabDisplayError(hwndDlg, ERR_GENERIC_CODE);
return ERR_GENERIC_CODE;
}
// Finally, restock the list view
UserTabFillUserList(hwndLV, hUserDatabase);
}
return NO_ERROR;
}
//
// Saves the dcc bypass setting
//
DWORD
UserTabSaveBypassDcc(
IN HWND hwndDlg)
{
HANDLE hUserDatabase = NULL;
BOOL bBypass = FALSE;
HWND hwndCtrl;
// Get reference to the misc database
RasSrvGetDatabaseHandle(
hwndDlg,
ID_USER_DATABASE,
&hUserDatabase);
hwndCtrl = GetDlgItem(hwndDlg, CID_UserTab_CB_BypassDcc);
if (hwndCtrl != NULL)
{
// Get the setting of the checkbox and commit it
bBypass = SendMessage(
hwndCtrl,
BM_GETCHECK,
0,
0) == BST_CHECKED;
usrSetDccBypass(hUserDatabase, bBypass);
}
return NO_ERROR;
}
//
// Handles WM_COMMAND messages on the user tab.
//
DWORD
UserTabCommand (
HWND hwndDlg,
WPARAM wParam,
LPARAM lParam)
{
DWORD dwIndex;
dwIndex =
ListView_GetSelectionMark(
GetDlgItem(hwndDlg, CID_UserTab_LV_Users));
switch (wParam) {
case CID_UserTab_PB_New:
UserTabHandleNewUserRequest(hwndDlg);
break;
case CID_UserTab_PB_Properties:
dwIndex =
UserTabHandleProperties(hwndDlg, dwIndex);
break;
case CID_UserTab_PB_Delete:
UserTabHandleDeleteUser(hwndDlg, dwIndex);
break;
case CID_UserTab_CB_BypassDcc:
UserTabSaveBypassDcc (hwndDlg);
break;
case CID_UserTab_PB_SwitchToMMC:
if (RassrvWarnMMCSwitch(hwndDlg))
{
PropSheet_PressButton(GetParent(hwndDlg), PSBTN_OK);
RassrvLaunchMMC(RASSRVUI_USERCONSOLE);
}
break;
}
return NO_ERROR;
}
//
// This dialog procedure responds to messages sent to the
// user tab.
//
INT_PTR
CALLBACK
UserTabDialogProc(
IN HWND hwndDlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam)
{
// Filter the customized list view messages
if (ListView_OwnerHandler(
hwndDlg,
uMsg,
wParam,
lParam,
LvDrawInfoCallback)
)
{
return TRUE;
}
// Filter the customized ras server ui page messages.
// By filtering messages through here, we are able to
// call RasSrvGetDatabaseHandle below
if (RasSrvMessageFilter(hwndDlg, uMsg, wParam, lParam))
{
return TRUE;
}
switch (uMsg)
{
case WM_INITDIALOG:
return FALSE;
case WM_HELP:
case WM_CONTEXTMENU:
{
RasSrvHelp (hwndDlg, uMsg, wParam, lParam, phmUserTab);
break;
}
case WM_NOTIFY:
{
NMHDR* pNotifyData;
NM_LISTVIEW* pLvNotifyData;
pNotifyData = (NMHDR*)lParam;
switch (pNotifyData->code) {
//
// Note: PSN_APPLY and PSN_CANCEL are handled
// by RasSrvMessageFilter
//
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
if (! GetWindowLongPtr(hwndDlg, GWLP_USERDATA))
{
UserTabInitializeDialog(
hwndDlg,
wParam,
lParam);
SetWindowLongPtr(
hwndDlg,
GWLP_USERDATA,
(LONG_PTR)1);
}
PropSheet_SetWizButtons(
GetParent(hwndDlg),
PSWIZB_NEXT | PSWIZB_BACK);
break;
// The check of an item is changing
case LVXN_SETCHECK:
pLvNotifyData = (NM_LISTVIEW*)lParam;
UserTabHandleUserCheck(
hwndDlg,
(DWORD)pLvNotifyData->iItem);
break;
case LVXN_DBLCLK:
pLvNotifyData = (NM_LISTVIEW*)lParam;
UserTabHandleProperties(
hwndDlg,
pLvNotifyData->iItem);
break;
}
}
break;
case WM_COMMAND:
UserTabCommand (hwndDlg, wParam, lParam);
break;
// Cleanup the work done at WM_INITDIALOG
case WM_DESTROY:
UserTabCleanupDialog(hwndDlg, wParam, lParam);
break;
}
return FALSE;
}