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
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;
|
|
}
|
|
|