2931 lines
82 KiB
C
2931 lines
82 KiB
C
/*++
|
||
|
||
Copyright (c) 1993, 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
logon.c
|
||
|
||
Abstract:
|
||
|
||
This module contains NetWare credential management code.
|
||
|
||
Author:
|
||
|
||
Rita Wong (ritaw) 15-Feb-1993
|
||
|
||
Revision History:
|
||
|
||
Yi-Hsin Sung (yihsins) 10-July-1993
|
||
Moved all dialog handling to nwdlg.c
|
||
|
||
Tommy Evans (tommye) 05-05-2000
|
||
Merged with code from Anoop (anoopa) to fix problem with
|
||
username/password not being stored correctly in the LOGON
|
||
list.
|
||
|
||
--*/
|
||
|
||
#include <nwclient.h>
|
||
#include <ntmsv1_0.h>
|
||
#include <nwsnames.h>
|
||
#include <nwcanon.h>
|
||
#include <validc.h>
|
||
#include <nwevent.h>
|
||
|
||
#include <nwdlg.h>
|
||
|
||
#include <nwreg.h>
|
||
#include <nwlsa.h>
|
||
#include <nwauth.h>
|
||
#include <nwapi.h>
|
||
#include <nwmisc.h>
|
||
#include <ndsapi32.h>
|
||
|
||
//-------------------------------------------------------------------//
|
||
// //
|
||
// Local Function Prototypes //
|
||
// //
|
||
//-------------------------------------------------------------------//
|
||
|
||
VOID
|
||
NwpInitializeRegistry(
|
||
IN LPWSTR NewUserSid,
|
||
OUT LPWSTR PreferredServer,
|
||
IN DWORD PreferredServerSize,
|
||
OUT LPWSTR NdsPreferredServer,
|
||
IN DWORD NdsPreferredServerSize,
|
||
OUT PDWORD LogonScriptOptions,
|
||
OUT PDWORD PrintOption
|
||
);
|
||
|
||
DWORD
|
||
NwpReadRegInfo(
|
||
IN HKEY WkstaKey,
|
||
IN LPWSTR CurrentUserSid,
|
||
OUT LPWSTR PreferredServer,
|
||
IN DWORD PreferredServerSize,
|
||
OUT LPWSTR NdsPreferredServer,
|
||
IN DWORD NdsPreferredServerSize,
|
||
OUT PDWORD PrintOption
|
||
);
|
||
|
||
DWORD
|
||
NwpGetCurrentUser(
|
||
OUT LPWSTR *SidString,
|
||
OUT LPWSTR *UserName
|
||
);
|
||
|
||
DWORD
|
||
NwpGetUserSid(
|
||
IN PLUID LogonId,
|
||
OUT LPWSTR *UserSidString
|
||
);
|
||
|
||
BOOL
|
||
NwpPollWorkstationStart(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
NwpSaveServiceCredential(
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password
|
||
);
|
||
|
||
DWORD
|
||
NwpSetCredentialInLsa(
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password
|
||
);
|
||
|
||
NTSTATUS NwNdsOpenRdrHandle(
|
||
OUT PHANDLE phNwRdrHandle
|
||
);
|
||
|
||
DWORD
|
||
NwpReadLogonScriptOptions(
|
||
IN LPWSTR CurrentUserSid,
|
||
OUT PDWORD pLogonScriptOptions,
|
||
OUT PDWORD pPreferredServerExists
|
||
);
|
||
|
||
LPWSTR
|
||
NwpConstructLogonScript(
|
||
IN DWORD LogonScriptOptions
|
||
);
|
||
|
||
VOID
|
||
NwpSelectServers(
|
||
IN HWND DialogHandle,
|
||
IN PCHANGE_PW_DLG_PARAM Credential
|
||
);
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////
|
||
|
||
DWORD
|
||
APIENTRY
|
||
NPLogonNotify(
|
||
PLUID lpLogonId,
|
||
LPCWSTR lpAuthentInfoType,
|
||
LPVOID lpAuthentInfo,
|
||
LPCWSTR lpPreviousAuthentInfoType,
|
||
LPVOID lpPreviousAuthentInfo,
|
||
LPWSTR lpStationName,
|
||
LPVOID StationHandle,
|
||
LPWSTR *lpLogonScript
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called by Winlogon after the interactive
|
||
user has successfully logged on to the local machine. We
|
||
are given the username and password, which
|
||
are displayed in the NetWare specific logon dialog if
|
||
needed.
|
||
|
||
Arguments:
|
||
|
||
lpLogonId - Ignored.
|
||
|
||
lpAuthentInfoType - Supplies a string which if is
|
||
L"MSV1_0:Interactive" means that the user has been logged
|
||
on by the Microsoft primary authenticator.
|
||
|
||
lpAuthentInfo - Supplies a pointer to the credentials which
|
||
the user was logged on with.
|
||
|
||
lpPreviousAuthentInfoType - Ignored.
|
||
|
||
lpPreviousAuthentInfo - Ignored.
|
||
|
||
lpStationName - Supplies a string which if it is L"WinSta_0"
|
||
means that Winlogon logged on the user.
|
||
|
||
StationHandle - Supplies the handle to the window which to display
|
||
our specific dialog.
|
||
|
||
lpLogonScripts - Receives a pointer to memory allocated by this
|
||
routine which contains a MULTI_SZ string of a program to run on
|
||
the command line with arguments, e.g. L"myprogram\0arg1\0arg2\0".
|
||
This memory must be freed by the caller with LocalFree.
|
||
|
||
Return Value:
|
||
|
||
WN_SUCCESS - Successfully saved default credentials.
|
||
|
||
WN_NOT_SUPPORTED - Primary authenticator is not Microsoft or
|
||
is not interactive via Winlogon.
|
||
|
||
ERROR_FILE_NOT_FOUND - Could not get our own provider DLL handle.
|
||
|
||
--*/
|
||
{
|
||
DWORD status = NO_ERROR;
|
||
INT_PTR Result = FALSE;
|
||
LPWSTR NewUserSid = NULL;
|
||
BOOL LogonAttempted = FALSE;
|
||
PMSV1_0_INTERACTIVE_LOGON NewLogonInfo =
|
||
(PMSV1_0_INTERACTIVE_LOGON) lpAuthentInfo;
|
||
|
||
WCHAR NwpServerBuffer[MAX_PATH + 1];
|
||
WCHAR NwpNdsServerBuffer[MAX_PATH + 1];
|
||
WCHAR NwpUserNameBuffer[NW_MAX_USERNAME_LEN + 1];
|
||
WCHAR NwpPasswordBuffer[NW_MAX_PASSWORD_LEN + 1];
|
||
DWORD NwpPrintOption = NW_PRINT_OPTION_DEFAULT;
|
||
DWORD NwpLogonScriptOptions = NW_LOGONSCRIPT_DEFAULT ;
|
||
BOOL cPasswordDlgClickOK = 0;
|
||
BOOL ServiceLogin = FALSE ;
|
||
BOOL NoLoginScript = FALSE ;
|
||
|
||
DBG_UNREFERENCED_PARAMETER(lpPreviousAuthentInfoType);
|
||
DBG_UNREFERENCED_PARAMETER(lpPreviousAuthentInfo);
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("\nNWPROVAU: NPLogonNotify\n"));
|
||
}
|
||
#endif
|
||
|
||
RpcTryExcept {
|
||
|
||
if (_wcsicmp(lpAuthentInfoType, L"MSV1_0:Interactive") != 0)
|
||
{
|
||
|
||
//
|
||
// We only handle a logon where Microsoft is the primary
|
||
// authenticator and it is an interactive logon via Winlogon.
|
||
//
|
||
status = WN_NOT_SUPPORTED;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
if (_wcsicmp(lpStationName, L"SvcCtl") == 0)
|
||
{
|
||
ServiceLogin = TRUE ;
|
||
}
|
||
|
||
|
||
//
|
||
// Initialize credential variables
|
||
//
|
||
NwpServerBuffer[0] = NW_INVALID_SERVER_CHAR;
|
||
NwpServerBuffer[1] = 0;
|
||
|
||
NwpNdsServerBuffer[0] = NW_INVALID_SERVER_CHAR;
|
||
NwpNdsServerBuffer[1] = 0;
|
||
|
||
RtlZeroMemory(NwpPasswordBuffer, sizeof(NwpPasswordBuffer));
|
||
|
||
if (NewLogonInfo->Password.Buffer != NULL) {
|
||
|
||
//
|
||
// check for max length to avoid overflowing.
|
||
//
|
||
if (NewLogonInfo->Password.Length >
|
||
(sizeof(NwpPasswordBuffer) - sizeof(WCHAR))) {
|
||
|
||
status = ERROR_INVALID_PARAMETER ;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
wcsncpy(
|
||
NwpPasswordBuffer,
|
||
NewLogonInfo->Password.Buffer,
|
||
NewLogonInfo->Password.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
|
||
RtlZeroMemory(NwpUserNameBuffer, sizeof(NwpUserNameBuffer));
|
||
|
||
if (NewLogonInfo->UserName.Buffer != NULL) {
|
||
|
||
//
|
||
// check for max length to avoid overflowing.
|
||
//
|
||
if (NewLogonInfo->UserName.Length >
|
||
(sizeof(NwpUserNameBuffer) - sizeof(WCHAR))) {
|
||
|
||
status = ERROR_INVALID_PARAMETER ;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
wcsncpy(
|
||
NwpUserNameBuffer,
|
||
NewLogonInfo->UserName.Buffer,
|
||
NewLogonInfo->UserName.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("\tMessageType : %lu\n", NewLogonInfo->MessageType));
|
||
KdPrint(("\tLogonDomainName : %ws\n", NewLogonInfo->LogonDomainName.Buffer));
|
||
KdPrint(("\tUserName : %ws\n", NwpUserNameBuffer));
|
||
KdPrint(("\tPassword : %ws\n", NwpPasswordBuffer));
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// if Interactive login, get user related info
|
||
//
|
||
if (!ServiceLogin)
|
||
{
|
||
//
|
||
// Get the user SID so that the user Netware username and
|
||
// preferred server is saved under a SID key rather than the
|
||
// LogonDomain*UserName key. We do this by making ourselves
|
||
// a logon process, and call the special MSV1.0 GetUserInfo
|
||
// interface.
|
||
//
|
||
status = NwpGetUserSid(lpLogonId, &NewUserSid);
|
||
|
||
if (status != NO_ERROR) {
|
||
goto EndOfTry;
|
||
}
|
||
|
||
//
|
||
// Initialize the registry:
|
||
// 1) Delete the CurrentUser value if it exists (was not clean up
|
||
// previously because user did not log off--rebooted machine).
|
||
// 2) Read the current user's PreferredServer and PrintOption
|
||
// value so that we can display the user's original
|
||
// preferred server.
|
||
//
|
||
NwpInitializeRegistry( NewUserSid,
|
||
NwpServerBuffer,
|
||
sizeof( NwpServerBuffer ) /
|
||
sizeof( NwpServerBuffer[0]),
|
||
NwpNdsServerBuffer,
|
||
sizeof( NwpNdsServerBuffer ) /
|
||
sizeof( NwpNdsServerBuffer[0]),
|
||
&NwpLogonScriptOptions,
|
||
&NwpPrintOption );
|
||
}
|
||
|
||
//
|
||
// Poll until the NetWare workstation has started, then validate
|
||
// the user credential.
|
||
//
|
||
if ( !NwpPollWorkstationStart() )
|
||
{
|
||
status = WN_NO_NETWORK;
|
||
KdPrint(("NWPROVAU: The Workstation Service is not running, give up\n", status));
|
||
goto EndOfTry;
|
||
}
|
||
|
||
//
|
||
// If service login, notify the redir with the username/passwd/
|
||
// LUID triplet and save the logon ID in the registry so that
|
||
// workstation can pick up if stopped and restarted.
|
||
//
|
||
if (ServiceLogin)
|
||
{
|
||
NwpSaveServiceCredential(
|
||
lpLogonId,
|
||
NwpUserNameBuffer,
|
||
NwpPasswordBuffer
|
||
);
|
||
|
||
(void) NwrLogonUser(
|
||
NULL,
|
||
lpLogonId,
|
||
NwpUserNameBuffer,
|
||
NwpPasswordBuffer,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
NW_PRINT_OPTION_DEFAULT //Terminal Server addition
|
||
);
|
||
|
||
} else {
|
||
|
||
//
|
||
// We need to save the user credentials at least once so that
|
||
// the CURRENTUSER Value is stored in the registry.
|
||
// This must be done before any RPC calls but after polling
|
||
// workstation start.
|
||
//
|
||
NwpSaveLogonCredential(
|
||
NewUserSid,
|
||
lpLogonId,
|
||
NwpUserNameBuffer,
|
||
NwpPasswordBuffer,
|
||
NULL // Don't save the preferred server
|
||
);
|
||
|
||
if (*NwpServerBuffer != NW_INVALID_SERVER_CHAR ) {
|
||
|
||
//
|
||
// Preferred server exists. So, try to log the user on.
|
||
//
|
||
INT nResult;
|
||
|
||
while (1)
|
||
{
|
||
WCHAR *DefaultTree = NULL ;
|
||
WCHAR *DefaultContext = NULL;
|
||
WCHAR *PreferredServer = NULL;
|
||
PROMPTDLGPARAM PasswdPromptParam;
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("\tNwrLogonUser\n"));
|
||
KdPrint(("\tUserName : %ws\n", NwpUserNameBuffer));
|
||
KdPrint(("\tServer : %ws\n", NwpServerBuffer));
|
||
}
|
||
#endif
|
||
|
||
|
||
//
|
||
// make sure user is logged off
|
||
//
|
||
(void) NwrLogoffUser(NULL, lpLogonId) ;
|
||
|
||
status = NwrLogonUser(
|
||
NULL,
|
||
lpLogonId,
|
||
NwpUserNameBuffer,
|
||
NwpPasswordBuffer,
|
||
NwpServerBuffer, // now either TREE or SERVER
|
||
NwpNdsServerBuffer, // Preferred Nds server if one exists
|
||
NULL,
|
||
0,
|
||
NwpPrintOption //***Terminal Server Added parameter
|
||
);
|
||
|
||
|
||
//
|
||
// tommye
|
||
//
|
||
// If the error is NO_SUCH_USER, see if the user name has any
|
||
// periods in it - if so, then we need to escape them (\.) and
|
||
// try the login again.
|
||
//
|
||
|
||
if (status == ERROR_NO_SUCH_USER) {
|
||
WCHAR EscapedName[NW_MAX_USERNAME_LEN * 2];
|
||
PWSTR pChar = NwpUserNameBuffer;
|
||
int i = 0;
|
||
BOOL bEscaped = FALSE;
|
||
|
||
RtlZeroMemory(EscapedName, sizeof(EscapedName));
|
||
|
||
do {
|
||
if (*pChar == L'.') {
|
||
EscapedName[i++] = '\\';
|
||
bEscaped = TRUE;
|
||
}
|
||
EscapedName[i++] = *pChar;
|
||
} while (*pChar++);
|
||
|
||
// Try the login again
|
||
|
||
if (bEscaped) {
|
||
|
||
status = NwrLogonUser(
|
||
NULL,
|
||
lpLogonId,
|
||
EscapedName,
|
||
NwpPasswordBuffer,
|
||
NwpServerBuffer, // now either TREE or SERVER
|
||
NwpNdsServerBuffer, // Preferred Nds server if one exists
|
||
NULL,
|
||
0,
|
||
NwpPrintOption //***Terminal Server Added parameter
|
||
);
|
||
if (status != ERROR_NO_SUCH_USER) { // if we matched a username, copy that name into buffer
|
||
//
|
||
// check for max length to avoid overflowing.
|
||
//
|
||
if (i < (sizeof(NwpUserNameBuffer))) {
|
||
wcsncpy(
|
||
NwpUserNameBuffer,
|
||
EscapedName,
|
||
i
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (status != ERROR_INVALID_PASSWORD)
|
||
break ;
|
||
|
||
PasswdPromptParam.UserName = NwpUserNameBuffer;
|
||
PasswdPromptParam.ServerName = NwpServerBuffer ;
|
||
PasswdPromptParam.Password = NwpPasswordBuffer;
|
||
PasswdPromptParam.PasswordSize = sizeof(NwpPasswordBuffer)/
|
||
sizeof(NwpPasswordBuffer[0]) ;
|
||
Result = DialogBoxParamW(
|
||
hmodNW,
|
||
MAKEINTRESOURCEW(DLG_PASSWORD_PROMPT),
|
||
(HWND) StationHandle,
|
||
(DLGPROC) NwpPasswdPromptDlgProc,
|
||
(LPARAM) &PasswdPromptParam
|
||
);
|
||
|
||
if (Result == -1 || Result == IDCANCEL)
|
||
{
|
||
status = ERROR_INVALID_PASSWORD ;
|
||
break ;
|
||
}
|
||
else
|
||
{
|
||
cPasswordDlgClickOK++;
|
||
}
|
||
}
|
||
|
||
if (status == NW_PASSWORD_HAS_EXPIRED)
|
||
{
|
||
WCHAR szNumber[16] ;
|
||
DWORD status1, dwMsgId, dwGraceLogins = 0 ;
|
||
LPWSTR apszInsertStrings[3] ;
|
||
|
||
//
|
||
// get the grace login count
|
||
//
|
||
status1 = NwGetGraceLoginCount(
|
||
NwpServerBuffer,
|
||
NwpUserNameBuffer,
|
||
&dwGraceLogins) ;
|
||
|
||
//
|
||
// if hit error, just dont use the number
|
||
//
|
||
if (status1 == NO_ERROR)
|
||
{
|
||
//
|
||
// tommye - MCS bug 251 - changed from SETPASS
|
||
// message (IDS_PASSWORD_EXPIRED) to
|
||
// Ctrl+Alt+Del message.
|
||
//
|
||
|
||
dwMsgId = IDS_PASSWORD_HAS_EXPIRED0; // use setpass.exe
|
||
wsprintfW(szNumber, L"%ld", dwGraceLogins) ;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// tommye - MCS bug 251 - changed from SETPASS
|
||
// message (IDS_PASSWORD_EXPIRED1) to
|
||
// Ctrl+Alt+Del message.
|
||
//
|
||
|
||
dwMsgId = IDS_PASSWORD_HAS_EXPIRED2 ; // use setpass.exe
|
||
}
|
||
|
||
apszInsertStrings[0] = NwpServerBuffer ;
|
||
apszInsertStrings[1] = szNumber ;
|
||
apszInsertStrings[2] = NULL ;
|
||
|
||
//
|
||
// put up message on password expiry
|
||
//
|
||
(void) NwpMessageBoxIns(
|
||
(HWND) StationHandle,
|
||
IDS_NETWARE_TITLE,
|
||
dwMsgId,
|
||
apszInsertStrings,
|
||
MB_OK | MB_SETFOREGROUND |
|
||
MB_ICONINFORMATION );
|
||
|
||
status = NO_ERROR ;
|
||
}
|
||
|
||
|
||
if ( status != NO_ERROR )
|
||
{
|
||
WCHAR *pszErrorLocation = NwpServerBuffer ;
|
||
DWORD dwMsgId = IDS_LOGIN_FAILURE_WARNING;
|
||
|
||
if (status == ERROR_ACCOUNT_RESTRICTION)
|
||
{
|
||
dwMsgId = IDS_LOGIN_ACC_RESTRICTION;
|
||
}
|
||
|
||
if (status == ERROR_SHARING_PAUSED)
|
||
{
|
||
status = IDS_LOGIN_DISABLED;
|
||
}
|
||
|
||
if (*NwpServerBuffer == L'*')
|
||
{
|
||
//
|
||
// Format into nicer string for user
|
||
//
|
||
WCHAR *pszTmp = LocalAlloc(LMEM_ZEROINIT,
|
||
(wcslen(NwpServerBuffer)+2) *
|
||
sizeof(WCHAR)) ;
|
||
if (pszTmp)
|
||
{
|
||
pszErrorLocation = pszTmp ;
|
||
|
||
//
|
||
// This code formats the NDS
|
||
// tree UNC to: Tree(Context)
|
||
//
|
||
wcscpy(pszErrorLocation, NwpServerBuffer+1) ;
|
||
|
||
if (pszTmp = wcschr(pszErrorLocation, L'\\'))
|
||
{
|
||
*pszTmp = L'(' ;
|
||
wcscat(pszErrorLocation, L")") ;
|
||
}
|
||
}
|
||
}
|
||
|
||
nResult = NwpMessageBoxError(
|
||
(HWND) StationHandle,
|
||
IDS_AUTH_FAILURE_TITLE,
|
||
dwMsgId,
|
||
status,
|
||
pszErrorLocation,
|
||
MB_YESNO | MB_ICONEXCLAMATION );
|
||
|
||
if (pszErrorLocation != NwpServerBuffer)
|
||
{
|
||
(void) LocalFree(pszErrorLocation) ;
|
||
}
|
||
|
||
//
|
||
// User chose not to select another preferred server,
|
||
// hence just return success.
|
||
//
|
||
if ( nResult == IDNO ) {
|
||
status = NO_ERROR;
|
||
NoLoginScript = TRUE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// The user might have changed the password in the password
|
||
// prompt dialog. Hence, we need to save the credentials
|
||
// ( the password ) again. Although the user might choose
|
||
// to select another server, he might canceled out of the
|
||
// login dialog. We must save logon credentials here no matter
|
||
// what.
|
||
//
|
||
NwpSaveLogonCredential(
|
||
NewUserSid,
|
||
lpLogonId,
|
||
NwpUserNameBuffer,
|
||
NwpPasswordBuffer,
|
||
NwpServerBuffer
|
||
);
|
||
}
|
||
|
||
//
|
||
// Only prompt user with the NetWare login dialog if
|
||
// no preferred server was found or an error occurred
|
||
// while authenticating the user.
|
||
//
|
||
if ( ( status != NO_ERROR)
|
||
|| (*NwpServerBuffer == NW_INVALID_SERVER_CHAR)
|
||
)
|
||
{
|
||
|
||
LOGINDLGPARAM LoginParam;
|
||
|
||
if ( cPasswordDlgClickOK > 0 )
|
||
{
|
||
// Password might have changed in the password prompt
|
||
// dialog. We want to always first use the NT password
|
||
// when validating a user on a server. Hence,
|
||
// we need to copy back the original NT password into
|
||
// NwpPasswordBuffer.
|
||
|
||
RtlZeroMemory(NwpPasswordBuffer, sizeof(NwpPasswordBuffer));
|
||
if (NewLogonInfo->Password.Buffer != NULL)
|
||
{
|
||
wcsncpy(
|
||
NwpPasswordBuffer,
|
||
NewLogonInfo->Password.Buffer,
|
||
NewLogonInfo->Password.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
}
|
||
|
||
LoginParam.UserName = NwpUserNameBuffer;
|
||
LoginParam.ServerName = NwpServerBuffer ;
|
||
LoginParam.Password = NwpPasswordBuffer;
|
||
LoginParam.NewUserSid = NewUserSid;
|
||
LoginParam.pLogonId = lpLogonId;
|
||
LoginParam.ServerNameSize = sizeof( NwpServerBuffer ) /
|
||
sizeof( NwpServerBuffer[0]);
|
||
LoginParam.PasswordSize = sizeof( NwpPasswordBuffer ) /
|
||
sizeof( NwpPasswordBuffer[0]);
|
||
LoginParam.LogonScriptOptions = NwpLogonScriptOptions;
|
||
LoginParam.PrintOption = NwpPrintOption;
|
||
Result = DialogBoxParamW(
|
||
hmodNW,
|
||
MAKEINTRESOURCEW(DLG_NETWARE_LOGIN),
|
||
(HWND) StationHandle,
|
||
(DLGPROC) NwpLoginDlgProc,
|
||
(LPARAM) &LoginParam
|
||
);
|
||
|
||
if (Result == -1) {
|
||
status = GetLastError();
|
||
KdPrint(("NWPROVAU: DialogBox failed %lu\n", status));
|
||
goto EndOfTry;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
EndOfTry: ;
|
||
|
||
}
|
||
RpcExcept(1) {
|
||
|
||
#if DBG
|
||
DWORD XceptCode;
|
||
|
||
|
||
XceptCode = RpcExceptionCode();
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NPLogonNotify: Exception code is x%08lx\n", XceptCode));
|
||
}
|
||
status = NwpMapRpcError(XceptCode);
|
||
#else
|
||
status = NwpMapRpcError(RpcExceptionCode());
|
||
#endif
|
||
|
||
}
|
||
RpcEndExcept;
|
||
|
||
if (!ServiceLogin && !NoLoginScript) {
|
||
|
||
DWORD fPServer = 0;
|
||
|
||
NwpReadLogonScriptOptions( NewUserSid,
|
||
&NwpLogonScriptOptions,
|
||
&fPServer );
|
||
if ( fPServer && ( NwpLogonScriptOptions & NW_LOGONSCRIPT_ENABLED ) )
|
||
{
|
||
*lpLogonScript = NwpConstructLogonScript( NwpLogonScriptOptions );
|
||
|
||
//
|
||
// set scripts to run synchronously. ignore error if we cant.
|
||
// not a disaster.
|
||
//
|
||
(void) NwrSetLogonScript(NULL, SYNC_LOGONSCRIPT) ;
|
||
}
|
||
else
|
||
{
|
||
*lpLogonScript = LocalAlloc(LMEM_ZEROINIT, sizeof(WCHAR));
|
||
}
|
||
}
|
||
else
|
||
*lpLogonScript = NULL;
|
||
|
||
if (NewUserSid != NULL) {
|
||
(void) LocalFree((HLOCAL) NewUserSid);
|
||
}
|
||
|
||
//
|
||
// Clear the password
|
||
//
|
||
RtlZeroMemory(NwpPasswordBuffer, sizeof(NwpPasswordBuffer));
|
||
|
||
if (status == WN_NO_NETWORK) {
|
||
//
|
||
// We don't care if the workstation has not started because
|
||
// we tuck the logon credential in the registry to be picked
|
||
// up by the workstation when it starts up. If we return
|
||
// ERROR_NO_NETWORK, MPR will poll us forever, causing us
|
||
// to continuously display the login dialog over and over
|
||
// again.
|
||
//
|
||
status = NO_ERROR;
|
||
}
|
||
|
||
if (status != NO_ERROR) {
|
||
SetLastError(status);
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
APIENTRY
|
||
NPPasswordChangeNotify(
|
||
LPCWSTR lpAuthentInfoType,
|
||
LPVOID lpAuthentInfo,
|
||
LPCWSTR lpPreviousAuthentInfoType,
|
||
LPVOID lpPreviousAuthentInfo,
|
||
LPWSTR lpStationName,
|
||
LPVOID StationHandle,
|
||
DWORD dwChangeInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called after the interactive user has selected to
|
||
change the password for the local logon via the Ctrl-Alt-Del dialog.
|
||
It is also called when the user cannot login because the password
|
||
has expired and must be changed.
|
||
|
||
Arguments:
|
||
|
||
lpAuthentInfoType - Supplies a string which if is
|
||
L"MSV1_0:Interactive" means that the user has been logged
|
||
on by the Microsoft primary authenticator.
|
||
|
||
lpAuthentInfo - Supplies a pointer to the credentials to
|
||
change to.
|
||
|
||
lpPreviousAuthentInfoType - Supplies a pointer to the old
|
||
credentials.
|
||
|
||
lpPreviousAuthentInfo - Ignored.
|
||
|
||
lpStationName - Supplies a string which if it is L"WinSta_0"
|
||
means that Winlogon logged on the user.
|
||
|
||
StationHandle - Supplies the handle to the window which to display
|
||
our specific dialog.
|
||
|
||
dwChangeInfo - Ignored.
|
||
|
||
Return Value:
|
||
|
||
WN_SUCCESS - successful operation.
|
||
|
||
WN_NOT_SUPPORTED - Only support change password if MS v1.0 is
|
||
the primary authenticator and is done through Winlogon.
|
||
|
||
WN_NO_NETWORK - Workstation service did not start.
|
||
|
||
--*/
|
||
{
|
||
DWORD status = NO_ERROR;
|
||
|
||
|
||
CHANGE_PW_DLG_PARAM Credential;
|
||
LPBYTE lpBuffer = NULL;
|
||
|
||
PMSV1_0_INTERACTIVE_LOGON NewCredential =
|
||
(PMSV1_0_INTERACTIVE_LOGON) lpAuthentInfo;
|
||
PMSV1_0_INTERACTIVE_LOGON OldCredential =
|
||
(PMSV1_0_INTERACTIVE_LOGON) lpPreviousAuthentInfo;
|
||
|
||
|
||
DBG_UNREFERENCED_PARAMETER(lpPreviousAuthentInfoType);
|
||
DBG_UNREFERENCED_PARAMETER(dwChangeInfo);
|
||
|
||
RtlZeroMemory(&Credential, sizeof(CHANGE_PW_DLG_PARAM));
|
||
|
||
RpcTryExcept {
|
||
|
||
if ((_wcsicmp(lpAuthentInfoType, L"MSV1_0:Interactive") != 0) ||
|
||
(_wcsicmp(lpStationName, L"WinSta0") != 0)) {
|
||
|
||
//
|
||
// We only handle a logon where Microsoft is the primary
|
||
// authenticator and it is an interactive logon via Winlogon.
|
||
//
|
||
status = WN_NOT_SUPPORTED;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
|
||
if (NewCredential == NULL || OldCredential == NULL) {
|
||
|
||
//
|
||
// Credentials not given to us by Winlogon or
|
||
// user did not type the old and new passwords.
|
||
//
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: PasswordChangeNotify got NULL for new and old credential pointers\n"));
|
||
}
|
||
#endif
|
||
|
||
(void) NwpMessageBoxError(
|
||
(HWND) StationHandle,
|
||
IDS_CHANGE_PASSWORD_TITLE,
|
||
IDS_BAD_PASSWORDS,
|
||
0,
|
||
NULL,
|
||
MB_OK | MB_ICONSTOP
|
||
);
|
||
|
||
status = WN_NOT_SUPPORTED;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
lpBuffer = LocalAlloc( LMEM_ZEROINIT,
|
||
( NW_MAX_USERNAME_LEN + 3 +
|
||
( 2 * NW_MAX_PASSWORD_LEN ) ) *
|
||
sizeof(WCHAR) );
|
||
|
||
if (lpBuffer == NULL) {
|
||
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto EndOfTry;
|
||
}
|
||
|
||
Credential.UserName = (LPWSTR) lpBuffer;
|
||
lpBuffer += (NW_MAX_USERNAME_LEN + 1) * sizeof(WCHAR);
|
||
Credential.OldPassword = (LPWSTR) lpBuffer;
|
||
lpBuffer += (NW_MAX_PASSWORD_LEN + 1) * sizeof(WCHAR);
|
||
Credential.NewPassword = (LPWSTR) lpBuffer;
|
||
|
||
if (NewCredential->UserName.Length == 0) {
|
||
|
||
//
|
||
// UserName is not specified. Try to get interactive user's name.
|
||
//
|
||
|
||
DWORD CharNeeded = NW_MAX_USERNAME_LEN + 1;
|
||
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: PasswordChangeNotify got empty string for username\n"));
|
||
}
|
||
#endif
|
||
|
||
if (! GetUserNameW(Credential.UserName, &CharNeeded)) {
|
||
|
||
//
|
||
// Could not get interactive user's name. Give up.
|
||
//
|
||
(void) NwpMessageBoxError(
|
||
(HWND) StationHandle,
|
||
IDS_CHANGE_PASSWORD_TITLE,
|
||
0,
|
||
ERROR_BAD_USERNAME,
|
||
NULL,
|
||
MB_OK | MB_ICONSTOP
|
||
);
|
||
}
|
||
}
|
||
else {
|
||
wcsncpy(
|
||
Credential.UserName,
|
||
NewCredential->UserName.Buffer,
|
||
NewCredential->UserName.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
|
||
if (OldCredential->Password.Length > 0)
|
||
{
|
||
wcsncpy(
|
||
Credential.OldPassword,
|
||
OldCredential->Password.Buffer,
|
||
OldCredential->Password.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
else
|
||
{
|
||
Credential.OldPassword[0] = 0;
|
||
}
|
||
|
||
if (NewCredential->Password.Length > 0)
|
||
{
|
||
wcsncpy(
|
||
Credential.NewPassword,
|
||
NewCredential->Password.Buffer,
|
||
NewCredential->Password.Length / sizeof(WCHAR)
|
||
);
|
||
}
|
||
else
|
||
{
|
||
Credential.NewPassword[0] = 0;
|
||
}
|
||
|
||
//
|
||
// Encode the passwords.
|
||
//
|
||
{
|
||
UCHAR EncodeSeed = NW_ENCODE_SEED2;
|
||
UNICODE_STRING PasswordStr;
|
||
|
||
|
||
RtlInitUnicodeString(&PasswordStr, Credential.OldPassword);
|
||
RtlRunEncodeUnicodeString(&EncodeSeed, &PasswordStr);
|
||
|
||
RtlInitUnicodeString(&PasswordStr, Credential.NewPassword);
|
||
RtlRunEncodeUnicodeString(&EncodeSeed, &PasswordStr);
|
||
}
|
||
|
||
NwpSelectServers(StationHandle, &Credential);
|
||
|
||
EndOfTry: ;
|
||
|
||
}
|
||
RpcExcept(1) {
|
||
|
||
#if DBG
|
||
DWORD XceptCode;
|
||
|
||
|
||
XceptCode = RpcExceptionCode();
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NPPasswordChangeNotify: Exception code is x%08lx\n", XceptCode));
|
||
}
|
||
status = NwpMapRpcError(XceptCode);
|
||
#else
|
||
status = NwpMapRpcError(RpcExceptionCode());
|
||
#endif
|
||
|
||
}
|
||
RpcEndExcept;
|
||
|
||
if (lpBuffer != NULL) {
|
||
LocalFree(lpBuffer);
|
||
}
|
||
|
||
if (status != NO_ERROR) {
|
||
SetLastError(status);
|
||
}
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NwpInitializeRegistry(
|
||
IN LPWSTR NewUserSid,
|
||
OUT LPWSTR PreferredServer,
|
||
IN DWORD PreferredServerSize,
|
||
OUT LPWSTR NdsPreferredServer,
|
||
IN DWORD NdsPreferredServerSize,
|
||
OUT PDWORD pLogonScriptOptions,
|
||
OUT PDWORD PrintOption
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the registry before putting up the
|
||
logon dialog.
|
||
1) Deletes the CurrentUser value if it was not cleaned up from
|
||
the last logoff.
|
||
2) Reads the current user's original PreferredServer value
|
||
3) Reads the current user's PrintOption value
|
||
|
||
Arguments:
|
||
|
||
NewUserSid - Supplies the newly logged on user's SID in string format
|
||
which is the key name to find the password and preferred server.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
LONG RegError;
|
||
HKEY WkstaKey;
|
||
|
||
|
||
//NwDeleteCurrentUser(); //Commented out for Multi-user code merge
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_OPTION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ,
|
||
&WkstaKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpInitializeRegistry open NWCWorkstation\\Parameters\\Option key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Get user's preferred server information.
|
||
//
|
||
(void) NwpReadRegInfo(WkstaKey,
|
||
NewUserSid,
|
||
PreferredServer,
|
||
PreferredServerSize,
|
||
NdsPreferredServer,
|
||
NdsPreferredServerSize,
|
||
PrintOption
|
||
);
|
||
|
||
(void) RegCloseKey(WkstaKey);
|
||
(void) NwpReadLogonScriptOptions( NewUserSid, pLogonScriptOptions, NULL );
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwpReadRegInfo(
|
||
IN HKEY WkstaKey,
|
||
IN LPWSTR CurrentUserSid,
|
||
OUT LPWSTR PreferredServer,
|
||
IN DWORD PreferredServerSize,
|
||
OUT LPWSTR NdsPreferredServer,
|
||
IN DWORD NdsPreferredServerSize,
|
||
OUT PDWORD PrintOption
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine reads the user's preferred server and print option
|
||
from the registry.
|
||
|
||
Arguments:
|
||
|
||
WkstaKey - Supplies the handle to the parameters key under the NetWare
|
||
workstation service key.
|
||
|
||
CurrentUserSid - Supplies the SID string of the user whose information
|
||
to read.
|
||
|
||
PreferredServer - Receives the user's preferred server.
|
||
|
||
PrintOption - Receives the user's print option.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
LONG RegError;
|
||
|
||
HKEY UserKey;
|
||
|
||
DWORD ValueType;
|
||
DWORD BytesNeeded;
|
||
|
||
//
|
||
// Open current user's key to read the original preferred server.
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
WkstaKey,
|
||
CurrentUserSid,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ,
|
||
&UserKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
|
||
if ( (RegError == ERROR_FILE_NOT_FOUND) ||
|
||
(RegError == ERROR_PATH_NOT_FOUND) ) {
|
||
|
||
//
|
||
// If key doesnt exist assume first time. Use default
|
||
// if present.
|
||
//
|
||
|
||
LONG RegError1 ;
|
||
HKEY WkstaParamKey ;
|
||
DWORD Disposition, dwScriptOptions,
|
||
dwScriptOptionsSize = sizeof(dwScriptOptions);
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters
|
||
//
|
||
RegError1 = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ,
|
||
&WkstaParamKey
|
||
);
|
||
|
||
if (RegError1 != NO_ERROR) {
|
||
|
||
return (DWORD) RegError; // return original error
|
||
}
|
||
|
||
BytesNeeded = PreferredServerSize;
|
||
|
||
RegError1 = RegQueryValueExW(
|
||
WkstaParamKey,
|
||
NW_DEFAULTSERVER_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) PreferredServer,
|
||
&BytesNeeded
|
||
);
|
||
|
||
|
||
if (RegError1 != NO_ERROR) {
|
||
|
||
(void) RegCloseKey(WkstaParamKey);
|
||
PreferredServer[0] = NW_INVALID_SERVER_CHAR;
|
||
PreferredServer[1] = 0;
|
||
return (DWORD) RegError; // return original error
|
||
}
|
||
|
||
RegError1 = RegQueryValueExW(
|
||
WkstaParamKey,
|
||
NW_DEFAULTSCRIPTOPTIONS_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) &dwScriptOptions,
|
||
&dwScriptOptionsSize
|
||
);
|
||
|
||
(void) RegCloseKey(WkstaParamKey);
|
||
|
||
if (RegError1 != NO_ERROR) {
|
||
|
||
dwScriptOptions = NW_LOGONSCRIPT_ENABLED |
|
||
NW_LOGONSCRIPT_4X_ENABLED ;
|
||
}
|
||
|
||
//
|
||
// We have a default. now write out the info for the current
|
||
// user now. Note we also write out the login script option.
|
||
// Errors here are not reported.
|
||
//
|
||
|
||
|
||
//
|
||
// Create the key under NWCWorkstation\Parameters\Option\<usersid>
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
WkstaKey,
|
||
CurrentUserSid,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | WRITE_DAC,
|
||
NULL, // security attr
|
||
&UserKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError == NO_ERROR) {
|
||
|
||
RegError = NwLibSetEverybodyPermission( UserKey,
|
||
KEY_SET_VALUE );
|
||
|
||
if ( RegError == NO_ERROR )
|
||
{
|
||
//
|
||
// Write the PreferredServer. Errors ignored.
|
||
//
|
||
RegError = RegSetValueExW(
|
||
UserKey,
|
||
NW_SERVER_VALUENAME,
|
||
0,
|
||
REG_SZ,
|
||
(LPVOID) PreferredServer,
|
||
(wcslen(PreferredServer) + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
(void) RegCloseKey(UserKey) ;
|
||
|
||
(void) NwpSaveLogonScriptOptions(
|
||
CurrentUserSid,
|
||
dwScriptOptions
|
||
) ;
|
||
}
|
||
else {
|
||
|
||
(void) RegCloseKey(UserKey) ;
|
||
}
|
||
}
|
||
|
||
|
||
*PrintOption = NW_PRINT_OPTION_DEFAULT;
|
||
return NO_ERROR;
|
||
|
||
}
|
||
return (DWORD) RegError;
|
||
}
|
||
|
||
|
||
//
|
||
// Read PreferredServer value
|
||
//
|
||
BytesNeeded = PreferredServerSize;
|
||
|
||
RegError = RegQueryValueExW(
|
||
UserKey,
|
||
NW_SERVER_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) PreferredServer,
|
||
&BytesNeeded
|
||
);
|
||
|
||
ASSERT(BytesNeeded <= PreferredServerSize);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Attempt to read original preferred server failed %lu\n",
|
||
RegError));
|
||
}
|
||
#endif
|
||
PreferredServer[0] = NW_INVALID_SERVER_CHAR; // Display login dialog
|
||
PreferredServer[1] = 0;
|
||
goto CleanExit;
|
||
}
|
||
|
||
//
|
||
// Read NdsPreferredServer value
|
||
//
|
||
BytesNeeded = NdsPreferredServerSize;
|
||
|
||
RegError = RegQueryValueExW(
|
||
UserKey,
|
||
NW_NDS_SERVER_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) NdsPreferredServer,
|
||
&BytesNeeded
|
||
);
|
||
|
||
ASSERT(BytesNeeded <= NdsPreferredServerSize);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Attempt to read NDS preferred server failed %lu\n",
|
||
RegError));
|
||
}
|
||
#endif
|
||
NdsPreferredServer[0] = 0;
|
||
NdsPreferredServer[1] = 0;
|
||
goto CleanExit;
|
||
}
|
||
|
||
|
||
CleanExit:
|
||
|
||
//
|
||
// Read PrintOption value into NwpPrintOption.
|
||
//
|
||
BytesNeeded = sizeof(PrintOption);
|
||
|
||
RegError = RegQueryValueExW(
|
||
UserKey,
|
||
NW_PRINTOPTION_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) PrintOption,
|
||
&BytesNeeded
|
||
);
|
||
|
||
if (RegError != NO_ERROR ) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Attempt to read original print option failed %lu\n", RegError));
|
||
}
|
||
#endif
|
||
|
||
*PrintOption = NW_PRINT_OPTION_DEFAULT;
|
||
}
|
||
|
||
(void) RegCloseKey(UserKey);
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
DWORD
|
||
NwpReadLogonScriptOptions(
|
||
IN LPWSTR CurrentUserSid,
|
||
OUT PDWORD pLogonScriptOptions,
|
||
OUT PDWORD pPreferredServerExists
|
||
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine reads the user's logon script options from the registry.
|
||
|
||
Arguments:
|
||
|
||
CurrentUserSid - Supplies the SID string of the user whose information
|
||
to read.
|
||
|
||
pLogonScriptOptions - Receives the user's script options
|
||
|
||
pPreferredServerExists - Prefered server specified
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
LONG RegError;
|
||
|
||
HKEY UserKey;
|
||
|
||
DWORD ValueType;
|
||
DWORD BytesNeeded;
|
||
HKEY WkstaKey;
|
||
WCHAR PreferredServer[MAX_PATH + 1];
|
||
|
||
//
|
||
// initialize output values
|
||
//
|
||
*pLogonScriptOptions = NW_LOGONSCRIPT_DEFAULT;
|
||
|
||
if (pPreferredServerExists)
|
||
*pPreferredServerExists = 0 ;
|
||
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_OPTION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ,
|
||
&WkstaKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpReadLogonScriptOptions open NWCWorkstation\\Parameters\\Option key unexpected error %lu!\n", RegError));
|
||
return (DWORD) RegError;
|
||
}
|
||
|
||
//
|
||
// Open current user's key
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
WkstaKey,
|
||
CurrentUserSid,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_READ,
|
||
&UserKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Open of CurrentUser %ws existing key failed %lu\n",
|
||
CurrentUserSid, RegError));
|
||
}
|
||
#endif
|
||
(void) RegCloseKey(WkstaKey);
|
||
return (DWORD) RegError;
|
||
}
|
||
|
||
|
||
//
|
||
// Read LogonScriptOption value
|
||
//
|
||
BytesNeeded = sizeof(*pLogonScriptOptions);
|
||
|
||
RegError = RegQueryValueExW(
|
||
UserKey,
|
||
NW_LOGONSCRIPT_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) pLogonScriptOptions,
|
||
&BytesNeeded
|
||
);
|
||
|
||
if (RegError != NO_ERROR ) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Attempt to read original logon script option failed %lu\n", RegError));
|
||
}
|
||
#endif
|
||
|
||
// leave *pLogonScriptOptions as 0
|
||
}
|
||
|
||
if ( pPreferredServerExists != NULL ) {
|
||
|
||
//
|
||
// Read PreferredServer value
|
||
//
|
||
BytesNeeded = sizeof( PreferredServer );
|
||
|
||
RegError = RegQueryValueExW(
|
||
UserKey,
|
||
NW_SERVER_VALUENAME,
|
||
NULL,
|
||
&ValueType,
|
||
(LPBYTE) PreferredServer,
|
||
&BytesNeeded
|
||
);
|
||
|
||
ASSERT(BytesNeeded <= sizeof(PreferredServer));
|
||
|
||
if (RegError != NO_ERROR) {
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: Attempt to read original preferred server failed %lu\n",
|
||
RegError));
|
||
}
|
||
#endif
|
||
*pPreferredServerExists = FALSE;
|
||
}
|
||
else {
|
||
if ( lstrcmp( PreferredServer, L"" ) )
|
||
*pPreferredServerExists = TRUE;
|
||
else
|
||
*pPreferredServerExists = FALSE;
|
||
}
|
||
}
|
||
|
||
(void) RegCloseKey(UserKey);
|
||
(void) RegCloseKey(WkstaKey);
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
LPWSTR
|
||
NwpConstructLogonScript(
|
||
IN DWORD LogonScriptOptions
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine constructs the multi-string for the logon script,
|
||
based on the options
|
||
|
||
Arguments:
|
||
|
||
LogonScriptOptions - Logon Script options
|
||
|
||
Return Value:
|
||
|
||
Allocated multi-string
|
||
|
||
--*/
|
||
{
|
||
LPWSTR pLogonScript;
|
||
DWORD BytesNeeded;
|
||
|
||
#define NW_NETWARE_SCRIPT_NAME L"nwscript.exe"
|
||
#define NW_NETWARE_DEBUG_NAME L"ntsd "
|
||
|
||
if ( !( LogonScriptOptions & NW_LOGONSCRIPT_ENABLED ) ) {
|
||
return NULL;
|
||
}
|
||
|
||
BytesNeeded = MAX_PATH * sizeof(WCHAR);
|
||
|
||
if (pLogonScript = LocalAlloc( LMEM_ZEROINIT, BytesNeeded))
|
||
{
|
||
DWORD dwSkipBytes = 0 ;
|
||
UINT retval ;
|
||
|
||
#if DBG
|
||
//
|
||
// if have exact match then start under NTSD.
|
||
//
|
||
if ( LogonScriptOptions == (NW_LOGONSCRIPT_ENABLED |
|
||
NW_LOGONSCRIPT_4X_ENABLED |
|
||
NW_LOGONSCRIPT_DEBUG) ) {
|
||
|
||
retval = GetSystemDirectory(pLogonScript,
|
||
BytesNeeded );
|
||
if (retval == 0) {
|
||
|
||
(void)LocalFree(pLogonScript) ;
|
||
return(NULL) ;
|
||
}
|
||
wcscat( pLogonScript, L"\\" );
|
||
wcscat( pLogonScript, NW_NETWARE_DEBUG_NAME );
|
||
dwSkipBytes = (retval * sizeof(WCHAR)) +
|
||
sizeof(NW_NETWARE_DEBUG_NAME) ;
|
||
BytesNeeded -= dwSkipBytes ;
|
||
}
|
||
#endif
|
||
|
||
retval = GetSystemDirectory(pLogonScript + (dwSkipBytes/sizeof(WCHAR)),
|
||
BytesNeeded );
|
||
|
||
if (retval == 0) {
|
||
|
||
(void)LocalFree(pLogonScript) ;
|
||
return(NULL) ;
|
||
}
|
||
|
||
wcscat( pLogonScript, L"\\" );
|
||
wcscat( pLogonScript, NW_NETWARE_SCRIPT_NAME );
|
||
}
|
||
|
||
return (pLogonScript);
|
||
|
||
}
|
||
|
||
DWORD
|
||
NwpSaveLogonScriptOptions(
|
||
IN LPWSTR CurrentUserSid,
|
||
IN DWORD LogonScriptOptions
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine saves the logon script options in the registry.
|
||
|
||
Arguments:
|
||
|
||
CurrentUserSid - Supplies the user's SID string
|
||
|
||
LogonScriptOptions - Logon script options
|
||
|
||
Return Value:
|
||
|
||
Error from registry
|
||
|
||
--*/
|
||
{
|
||
LONG RegError;
|
||
HKEY WkstaOptionKey;
|
||
HKEY CurrentUserOptionKey;
|
||
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_OPTION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | KEY_CREATE_SUB_KEY | DELETE,
|
||
&WkstaOptionKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonScriptOptions open NWCWorkstation\\Parameters\\Option key unexpected error %lu!\n", RegError));
|
||
return RegError;
|
||
}
|
||
|
||
//
|
||
// Open the <NewUser> key under Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
WkstaOptionKey,
|
||
CurrentUserSid,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
&CurrentUserOptionKey
|
||
);
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonScriptOptions failed to save options %lu\n", RegError));
|
||
return RegError;
|
||
}
|
||
|
||
//
|
||
// Write the options
|
||
//
|
||
RegError = RegSetValueExW(
|
||
CurrentUserOptionKey,
|
||
NW_LOGONSCRIPT_VALUENAME,
|
||
0,
|
||
REG_DWORD,
|
||
(LPVOID) &LogonScriptOptions,
|
||
sizeof(LogonScriptOptions)
|
||
);
|
||
|
||
(void) RegCloseKey(CurrentUserOptionKey);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonScriptOptions failed to save options %lu\n", RegError));
|
||
}
|
||
|
||
return RegError;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NwpSaveLogonCredential(
|
||
IN LPWSTR NewUserSid,
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password,
|
||
IN LPWSTR PreferredServer OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine saves the user logon credential in the registry
|
||
and LSA's memory. This is normally called when NwrLogonUser is
|
||
successful.
|
||
|
||
Arguments:
|
||
|
||
NewUserSid - Supplies the newly logged on user's SID string to be
|
||
set as the CurrentUser value as well as the name of the key for
|
||
the user's preferred server.
|
||
|
||
LogonId - Supplies the user's logon ID. If NULL is specified,
|
||
just read the existing logon ID from the registry rather
|
||
than save a new one.
|
||
|
||
UserName - Supplies the name of the user.
|
||
|
||
Password - Supplies the password which the user wants to use on
|
||
the NetWare network.
|
||
|
||
PreferredServer - Supplies the name of the preferred server.
|
||
|
||
Return Value:
|
||
|
||
Error from redirector if login is rejected.
|
||
|
||
--*/
|
||
{
|
||
|
||
DWORD status;
|
||
|
||
LONG RegError;
|
||
HKEY WkstaOptionKey;
|
||
HKEY NewUserOptionKey;
|
||
|
||
#define SIZE_OF_LOGONID_TOKEN_INFORMATION sizeof( ULONG )
|
||
|
||
HKEY InteractiveLogonKey;
|
||
HKEY LogonIdKey;
|
||
DWORD Disposition;
|
||
WCHAR LogonIdKeyName[NW_MAX_LOGON_ID_LEN];
|
||
HANDLE TokenHandle;
|
||
UCHAR TokenInformation[ SIZE_OF_LOGONID_TOKEN_INFORMATION ];
|
||
ULONG ReturnLength;
|
||
ULONG WinStationId = 0L;
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential: %ws, %ws, %ws, %ws\n",
|
||
NewUserSid, UserName, Password, PreferredServer));
|
||
}
|
||
#endif
|
||
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_OPTION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | KEY_CREATE_SUB_KEY | DELETE,
|
||
&WkstaOptionKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open NWCWorkstation\\Parameters\\Option key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Open the <NewUser> key under Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
WkstaOptionKey,
|
||
NewUserSid,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
&NewUserOptionKey
|
||
);
|
||
|
||
|
||
if (RegError == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
DWORD Disposition;
|
||
|
||
//
|
||
// Create <NewUser> key under NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
WkstaOptionKey,
|
||
NewUserSid,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | WRITE_DAC,
|
||
NULL, // security attr
|
||
&NewUserOptionKey,
|
||
&Disposition
|
||
);
|
||
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential create Option\\%ws key unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
RegError = NwLibSetEverybodyPermission( NewUserOptionKey,
|
||
KEY_SET_VALUE );
|
||
|
||
if ( RegError != NO_ERROR )
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential set security on Option\\%ws key unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
}
|
||
else if (RegError != NO_ERROR)
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open Option\\%ws unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
|
||
//
|
||
// Successfully opened or created an existing user entry.
|
||
// We will now save the credential in LSA.
|
||
//
|
||
status = NwpSetCredentialInLsa(
|
||
LogonId,
|
||
UserName,
|
||
Password
|
||
);
|
||
|
||
if (status != NO_ERROR) {
|
||
//
|
||
// Could not save new credential.
|
||
//
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to set credential %lu\n", status));
|
||
}
|
||
|
||
|
||
//
|
||
// If PreferredServer is not supplied, then that means we don't want to
|
||
// save the preferred server into the registry.
|
||
//
|
||
|
||
if (ARGUMENT_PRESENT(PreferredServer))
|
||
{
|
||
//
|
||
// Write the PreferredServer
|
||
//
|
||
RegError = RegSetValueExW(
|
||
NewUserOptionKey,
|
||
NW_SERVER_VALUENAME,
|
||
0,
|
||
REG_SZ,
|
||
(LPVOID) PreferredServer,
|
||
(wcslen(PreferredServer) + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save PreferredServer %ws %lu\n", PreferredServer, RegError));
|
||
}
|
||
}
|
||
|
||
(void) RegCloseKey(NewUserOptionKey);
|
||
|
||
//
|
||
// Write the logon ID to the registry.
|
||
// This replaces the single user CURRENTUSER stuff
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\InteractiveLogon, create if does not exist
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_INTERACTIVE_LOGON_REGKEY,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&InteractiveLogonKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open NWCWorkstation\\Parameters\\InteractiveLogon key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
NwLuidToWStr(LogonId, LogonIdKeyName);
|
||
|
||
//
|
||
// Create the logon ID key under ServiceLogon
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
InteractiveLogonKey,
|
||
LogonIdKeyName,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&LogonIdKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveInteractiveCredential create NWCWorkstation\\Parameters\\InteractiveLogon\\<LogonId> key unexpected error %lu!\n", RegError));
|
||
RegCloseKey(InteractiveLogonKey);
|
||
return;
|
||
}
|
||
|
||
// We can use OpenProcessToken because this thread is a client
|
||
// I.E. It should be WinLogon
|
||
|
||
if ( !OpenProcessToken( GetCurrentProcess(),
|
||
TOKEN_READ,
|
||
&TokenHandle ))
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential OpenThreadToken failed: Error %d\n", GetLastError()));
|
||
goto NoWinStation;
|
||
}
|
||
|
||
// notice that we've allocated enough space for the
|
||
// TokenInformation structure. so if we fail, we
|
||
// return a NULL pointer indicating failure
|
||
|
||
|
||
if ( !GetTokenInformation( TokenHandle,
|
||
TokenSessionId,
|
||
TokenInformation,
|
||
sizeof( TokenInformation ),
|
||
&ReturnLength ))
|
||
{
|
||
KdPrint(("NWPROVAU NwpSaveLogonCredential: GetTokenInformation failed: Error %d\n",
|
||
GetLastError()));
|
||
CloseHandle( TokenHandle );
|
||
goto NoWinStation;
|
||
}
|
||
|
||
|
||
WinStationId = *(PULONG)TokenInformation;
|
||
|
||
CloseHandle( TokenHandle );
|
||
|
||
NoWinStation:
|
||
|
||
//
|
||
// Write the WinStation ID to the registry.
|
||
//
|
||
RegError = RegSetValueExW(
|
||
LogonIdKey,
|
||
NW_WINSTATION_VALUENAME,
|
||
0,
|
||
REG_BINARY,
|
||
(LPVOID) &WinStationId,
|
||
sizeof(WinStationId)
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save Winstation ID %lu\n", RegError));
|
||
}
|
||
|
||
RegError = RegSetValueExW(
|
||
LogonIdKey,
|
||
NW_SID_VALUENAME,
|
||
0,
|
||
REG_SZ,
|
||
(LPVOID) NewUserSid,
|
||
(wcslen(NewUserSid) + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save NewUser %ws %lu\n", NewUserSid, RegError));
|
||
}
|
||
|
||
RegCloseKey(LogonIdKey);
|
||
RegCloseKey(InteractiveLogonKey);
|
||
|
||
}
|
||
|
||
VOID
|
||
NwpSaveLogonCredentialMultiUser(
|
||
IN LPWSTR NewUserSid,
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password,
|
||
IN LPWSTR PreferredServer OPTIONAL
|
||
)
|
||
{
|
||
DWORD status;
|
||
|
||
LONG RegError;
|
||
HKEY WkstaOptionKey;
|
||
HKEY NewUserOptionKey;
|
||
#define SIZE_OF_LOGONID_TOKEN_INFORMATION sizeof( ULONG )
|
||
|
||
HKEY InteractiveLogonKey;
|
||
HKEY LogonIdKey;
|
||
DWORD Disposition;
|
||
WCHAR LogonIdKeyName[NW_MAX_LOGON_ID_LEN];
|
||
HANDLE TokenHandle;
|
||
UCHAR TokenInformation[ SIZE_OF_LOGONID_TOKEN_INFORMATION ];
|
||
ULONG ReturnLength;
|
||
ULONG WinStationId = 0L;
|
||
|
||
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_WORKSTATION_OPTION_REGKEY,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | KEY_CREATE_SUB_KEY | DELETE,
|
||
&WkstaOptionKey
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open NWCWorkstation\\Parameters\\Option key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
|
||
//
|
||
// Open the <NewUser> key under Option
|
||
//
|
||
RegError = RegOpenKeyExW(
|
||
WkstaOptionKey,
|
||
NewUserSid,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
&NewUserOptionKey
|
||
);
|
||
|
||
|
||
if (RegError == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
DWORD Disposition;
|
||
|
||
//
|
||
// Create <NewUser> key under NWCWorkstation\Parameters\Option
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
WkstaOptionKey,
|
||
NewUserSid,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE | WRITE_DAC,
|
||
NULL, // security attr
|
||
&NewUserOptionKey,
|
||
&Disposition
|
||
);
|
||
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential create Option\\%ws key unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
RegError = NwLibSetEverybodyPermission( NewUserOptionKey,
|
||
KEY_SET_VALUE );
|
||
|
||
if ( RegError != NO_ERROR )
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential set security on Option\\%ws key unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
}
|
||
else if (RegError != NO_ERROR)
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open Option\\%ws unexpected error %lu!\n", NewUserSid, RegError));
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
return;
|
||
}
|
||
|
||
(void) RegCloseKey(WkstaOptionKey);
|
||
|
||
//
|
||
// Successfully opened or created an existing user entry.
|
||
// We will now save the credential in LSA.
|
||
//
|
||
status = NwpSetCredentialInLsa(
|
||
LogonId,
|
||
UserName,
|
||
Password
|
||
);
|
||
|
||
if (status != NO_ERROR) {
|
||
//
|
||
// Could not save new credential.
|
||
//
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to set credential %lu\n", status));
|
||
}
|
||
|
||
|
||
//
|
||
// If PreferredServer is not supplied, then that means we don't want to
|
||
// save the preferred server into the registry.
|
||
//
|
||
|
||
if (ARGUMENT_PRESENT(PreferredServer))
|
||
{
|
||
//
|
||
// Write the PreferredServer
|
||
//
|
||
RegError = RegSetValueExW(
|
||
NewUserOptionKey,
|
||
NW_SERVER_VALUENAME,
|
||
0,
|
||
REG_SZ,
|
||
(LPVOID) PreferredServer,
|
||
(wcslen(PreferredServer) + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save PreferredServer %ws %lu\n", PreferredServer, RegError));
|
||
}
|
||
}
|
||
|
||
(void) RegCloseKey(NewUserOptionKey);
|
||
|
||
//
|
||
// Write the logon ID to the registry.
|
||
// This replaces the single user CURRENTUSER stuff
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\InteractiveLogon, create if does not exist
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_INTERACTIVE_LOGON_REGKEY,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&InteractiveLogonKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential open NWCWorkstation\\Parameters\\InteractiveLogon key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
NwLuidToWStr(LogonId, LogonIdKeyName);
|
||
|
||
//
|
||
// Create the logon ID key under ServiceLogon
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
InteractiveLogonKey,
|
||
LogonIdKeyName,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&LogonIdKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveInteractiveCredential create NWCWorkstation\\Parameters\\InteractiveLogon\\<LogonId> key unexpected error %lu!\n", RegError));
|
||
RegCloseKey(InteractiveLogonKey);
|
||
return;
|
||
}
|
||
|
||
// We can use OpenProcessToken because this thread is a client
|
||
// I.E. It should be WinLogon
|
||
|
||
if ( !OpenProcessToken( GetCurrentProcess(),
|
||
TOKEN_READ,
|
||
&TokenHandle ))
|
||
{
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential OpenThreadToken failed: Error %d\n", GetLastError()));
|
||
goto NoWinStation;
|
||
}
|
||
|
||
// notice that we've allocated enough space for the
|
||
// TokenInformation structure. so if we fail, we
|
||
// return a NULL pointer indicating failure
|
||
|
||
|
||
if ( !GetTokenInformation( TokenHandle,
|
||
TokenSessionId,
|
||
TokenInformation,
|
||
sizeof( TokenInformation ),
|
||
&ReturnLength ))
|
||
{
|
||
KdPrint(("NWPROVAU NwpSaveLogonCredential: GetTokenInformation failed: Error %d\n",
|
||
GetLastError()));
|
||
CloseHandle( TokenHandle );
|
||
goto NoWinStation;
|
||
}
|
||
|
||
|
||
WinStationId = *(PULONG)TokenInformation;
|
||
|
||
CloseHandle( TokenHandle );
|
||
|
||
NoWinStation:
|
||
|
||
//
|
||
// Write the WinStation ID to the registry.
|
||
//
|
||
RegError = RegSetValueExW(
|
||
LogonIdKey,
|
||
NW_WINSTATION_VALUENAME,
|
||
0,
|
||
REG_BINARY,
|
||
(LPVOID) &WinStationId,
|
||
sizeof(WinStationId)
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save Winstation ID %lu\n", RegError));
|
||
}
|
||
|
||
RegError = RegSetValueExW(
|
||
LogonIdKey,
|
||
NW_SID_VALUENAME,
|
||
0,
|
||
REG_SZ,
|
||
(LPVOID) NewUserSid,
|
||
(wcslen(NewUserSid) + 1) * sizeof(WCHAR)
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveLogonCredential failed to save NewUser %ws %lu\n", NewUserSid, RegError));
|
||
}
|
||
|
||
RegCloseKey(LogonIdKey);
|
||
RegCloseKey(InteractiveLogonKey);
|
||
|
||
}
|
||
|
||
VOID
|
||
NwpSaveServiceCredential(
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine saves the service logon ID in the registry and
|
||
the credential in LSA's memory.
|
||
|
||
Arguments:
|
||
|
||
LogonId - Supplies the service's logon ID.
|
||
|
||
UserName - Supplies the name of the service.
|
||
|
||
Password - Supplies the password of the service.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
|
||
LONG RegError;
|
||
HKEY ServiceLogonKey;
|
||
HKEY LogonIdKey;
|
||
|
||
DWORD Disposition;
|
||
WCHAR LogonIdKeyName[NW_MAX_LOGON_ID_LEN];
|
||
|
||
//
|
||
// Write the logon ID to the registry.
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
||
// \NWCWorkstation\Parameters\ServiceLogon, create if does not exist
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
NW_SERVICE_LOGON_REGKEY,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&ServiceLogonKey,
|
||
&Disposition
|
||
);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveServiceCredential open NWCWorkstation\\Parameters\\ServiceLogon key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
NwLuidToWStr(LogonId, LogonIdKeyName);
|
||
|
||
//
|
||
// Create the logon ID key under ServiceLogon
|
||
//
|
||
RegError = RegCreateKeyExW(
|
||
ServiceLogonKey,
|
||
LogonIdKeyName,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_WRITE,
|
||
NULL, // security attr
|
||
&LogonIdKey,
|
||
&Disposition
|
||
);
|
||
|
||
RegCloseKey(ServiceLogonKey);
|
||
|
||
if (RegError != NO_ERROR) {
|
||
KdPrint(("NWPROVAU: NwpSaveServiceCredential create NWCWorkstation\\Parameters\\ServiceLogon\\<LogonId> key unexpected error %lu!\n", RegError));
|
||
return;
|
||
}
|
||
|
||
RegCloseKey(LogonIdKey);
|
||
|
||
//
|
||
// Save the service logon credential in LSA.
|
||
//
|
||
status = NwpSetCredentialInLsa(
|
||
LogonId,
|
||
UserName,
|
||
Password
|
||
);
|
||
|
||
if (status != NO_ERROR) {
|
||
//
|
||
// Could not save new credential.
|
||
//
|
||
KdPrint(("NWPROVAU: NwpSaveServiceCredential failed to set credential %lu\n", status));
|
||
}
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwpGetUserSid(
|
||
IN PLUID LogonId,
|
||
OUT LPWSTR *UserSidString
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine looks up the SID of a user given the user's logon ID.
|
||
It does this by making the current process a logon process and then
|
||
call to LSA to get the user SID.
|
||
|
||
Arguments:
|
||
|
||
LogonId - Supplies the logon ID of the user to lookup the SID.
|
||
|
||
UserSidString - Receives a pointer to a buffer allocated by this routine
|
||
which contains the user SID in string form. This must be freed with
|
||
LocalFree when done.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
NTSTATUS ntstatus;
|
||
NTSTATUS AuthPackageStatus;
|
||
|
||
STRING InputString;
|
||
LSA_OPERATIONAL_MODE SecurityMode = 0;
|
||
|
||
HANDLE LsaHandle;
|
||
ULONG AuthPackageId;
|
||
|
||
MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;
|
||
PMSV1_0_GETUSERINFO_RESPONSE UserInfoResponse = NULL;
|
||
ULONG UserInfoResponseLength;
|
||
|
||
|
||
|
||
|
||
//
|
||
// Register this process as a logon process so that we can call
|
||
// MS V 1.0 authentication package.
|
||
//
|
||
RtlInitString(&InputString, "Microsoft NetWare Credential Manager");
|
||
|
||
ntstatus = LsaRegisterLogonProcess(
|
||
&InputString,
|
||
&LsaHandle,
|
||
&SecurityMode
|
||
);
|
||
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: LsaRegisterLogonProcess returns x%08lx\n",
|
||
ntstatus));
|
||
return RtlNtStatusToDosError(ntstatus);
|
||
}
|
||
|
||
//
|
||
// Look up the MS V1.0 authentication package
|
||
//
|
||
RtlInitString(&InputString, MSV1_0_PACKAGE_NAME);
|
||
|
||
ntstatus = LsaLookupAuthenticationPackage(
|
||
LsaHandle,
|
||
&InputString,
|
||
&AuthPackageId
|
||
);
|
||
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: LsaLookupAuthenticationPackage returns x%08lx\n",
|
||
ntstatus));
|
||
status = RtlNtStatusToDosError(ntstatus);
|
||
goto CleanExit;
|
||
}
|
||
|
||
//
|
||
// Ask authentication package for user information.
|
||
//
|
||
UserInfoRequest.MessageType = MsV1_0GetUserInfo;
|
||
RtlCopyLuid(&UserInfoRequest.LogonId, LogonId);
|
||
|
||
ntstatus = LsaCallAuthenticationPackage(
|
||
LsaHandle,
|
||
AuthPackageId,
|
||
&UserInfoRequest,
|
||
sizeof(MSV1_0_GETUSERINFO_REQUEST),
|
||
(PVOID *) &UserInfoResponse,
|
||
&UserInfoResponseLength,
|
||
&AuthPackageStatus
|
||
);
|
||
|
||
if (NT_SUCCESS(ntstatus)) {
|
||
ntstatus = AuthPackageStatus;
|
||
}
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: LsaCallAuthenticationPackage returns x%08lx\n",
|
||
ntstatus));
|
||
status = RtlNtStatusToDosError(ntstatus);
|
||
goto CleanExit;
|
||
}
|
||
|
||
//
|
||
// Convert the SID to string. This routine also allocates the
|
||
// output buffer.
|
||
//
|
||
status = NwpConvertSid(
|
||
UserInfoResponse->UserSid,
|
||
UserSidString
|
||
);
|
||
|
||
CleanExit:
|
||
if (UserInfoResponse != NULL) {
|
||
(void) LsaFreeReturnBuffer((PVOID) UserInfoResponse);
|
||
}
|
||
|
||
(void) LsaDeregisterLogonProcess(LsaHandle);
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
DWORD
|
||
NwpConvertSid(
|
||
IN PSID Sid,
|
||
OUT LPWSTR *UserSidString
|
||
)
|
||
{
|
||
NTSTATUS ntstatus;
|
||
UNICODE_STRING SidString;
|
||
|
||
|
||
//
|
||
// Initialize output pointer
|
||
//
|
||
*UserSidString = NULL;
|
||
|
||
ntstatus = RtlConvertSidToUnicodeString(
|
||
&SidString,
|
||
Sid,
|
||
TRUE // Allocate destination string
|
||
);
|
||
|
||
if (ntstatus != STATUS_SUCCESS) {
|
||
KdPrint(("NWPROVAU: RtlConvertSidToUnicodeString returns %08lx\n",
|
||
ntstatus));
|
||
return RtlNtStatusToDosError(ntstatus);
|
||
}
|
||
|
||
//
|
||
// Create the buffer to return the SID string
|
||
//
|
||
if ((*UserSidString = (LPVOID) LocalAlloc(
|
||
LMEM_ZEROINIT,
|
||
SidString.Length + sizeof(WCHAR)
|
||
)) == NULL) {
|
||
RtlFreeUnicodeString(&SidString);
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
memcpy(*UserSidString, SidString.Buffer, SidString.Length);
|
||
|
||
RtlFreeUnicodeString(&SidString);
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NwpConvertSid got %ws\n", *UserSidString));
|
||
}
|
||
#endif
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
BOOL
|
||
NwpPollWorkstationStart(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine polls for the workstation to complete starting.
|
||
It gives up after 90 seconds.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Returns TRUE if the NetWare workstation is running; FALSE otherwise.
|
||
|
||
--*/
|
||
{
|
||
DWORD err;
|
||
SC_HANDLE ScManager = NULL;
|
||
SC_HANDLE Service = NULL;
|
||
SERVICE_STATUS ServiceStatus;
|
||
DWORD TryCount = 0;
|
||
BOOL Started = FALSE;
|
||
|
||
|
||
if ((ScManager = OpenSCManager(
|
||
NULL,
|
||
NULL,
|
||
SC_MANAGER_CONNECT
|
||
)) == (SC_HANDLE) NULL) {
|
||
|
||
err = GetLastError();
|
||
|
||
KdPrint(("NWPROVAU: NwpPollWorkstationStart: OpenSCManager failed %lu\n",
|
||
err));
|
||
goto CleanExit;
|
||
}
|
||
|
||
if ((Service = OpenService(
|
||
ScManager,
|
||
NW_WORKSTATION_SERVICE,
|
||
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG
|
||
)) == (SC_HANDLE) NULL) {
|
||
|
||
err = GetLastError();
|
||
|
||
(void) CloseServiceHandle(ScManager);
|
||
|
||
KdPrint(("NWPROVAU: NwpPollWorkstationStart: OpenService failed %lu\n",
|
||
err));
|
||
goto CleanExit;
|
||
}
|
||
|
||
|
||
do {
|
||
if (! QueryServiceStatus(
|
||
Service,
|
||
&ServiceStatus
|
||
)) {
|
||
|
||
err = GetLastError();
|
||
KdPrint(("NWPROVAU: NwpPollWorkstationStart: QueryServiceStatus failed %lu\n",
|
||
err));
|
||
goto CleanExit;
|
||
}
|
||
|
||
if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
|
||
(ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
|
||
(ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) ||
|
||
(ServiceStatus.dwCurrentState == SERVICE_PAUSED) ) {
|
||
|
||
Started = TRUE;
|
||
}
|
||
else if (ServiceStatus.dwCurrentState == SERVICE_START_PENDING ||
|
||
(ServiceStatus.dwCurrentState == SERVICE_STOPPED &&
|
||
ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED)) {
|
||
|
||
//
|
||
// If workstation is stopped and never started before but it's
|
||
// not auto-start, don't poll.
|
||
//
|
||
if (TryCount == 0 &&
|
||
ServiceStatus.dwCurrentState == SERVICE_STOPPED &&
|
||
ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) {
|
||
|
||
BYTE OutBuffer[sizeof(QUERY_SERVICE_CONFIGW) + 256];
|
||
DWORD BytesNeeded;
|
||
|
||
|
||
if (QueryServiceConfigW(
|
||
Service,
|
||
(LPQUERY_SERVICE_CONFIGW) OutBuffer,
|
||
sizeof(OutBuffer),
|
||
&BytesNeeded
|
||
)) {
|
||
|
||
if (((LPQUERY_SERVICE_CONFIGW) OutBuffer)->dwStartType !=
|
||
SERVICE_AUTO_START) {
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NwpPollWorkstationStart: Not waiting for the workstation to start\n"));
|
||
}
|
||
#endif
|
||
|
||
goto CleanExit;
|
||
}
|
||
}
|
||
else {
|
||
err = GetLastError();
|
||
KdPrint(("NWPROVAU: QueryServiceConfig failed %lu, BytesNeeded %lu\n",
|
||
err, BytesNeeded));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Wait only if the workstation is start pending, or it has not
|
||
// been attempted to start before.
|
||
//
|
||
|
||
Sleep(5000); // Sleep for 5 seconds before rechecking.
|
||
TryCount++;
|
||
}
|
||
else {
|
||
goto CleanExit;
|
||
}
|
||
|
||
} while (! Started && TryCount < 18);
|
||
|
||
if (Started) {
|
||
|
||
#if DBG
|
||
IF_DEBUG(LOGON) {
|
||
KdPrint(("NWPROVAU: NetWare workstation is started after we've polled %lu times\n",
|
||
TryCount));
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
CleanExit:
|
||
if (ScManager != NULL) {
|
||
(void) CloseServiceHandle(ScManager);
|
||
}
|
||
|
||
if (Service != NULL) {
|
||
(void) CloseServiceHandle(Service);
|
||
}
|
||
|
||
return Started;
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
NwpSetCredentialInLsa(
|
||
IN PLUID LogonId,
|
||
IN LPWSTR UserName,
|
||
IN LPWSTR Password
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine calls to the NetWare authentication package to save
|
||
the user credential.
|
||
|
||
Arguments:
|
||
|
||
LogonId - Supplies the logon ID of the user.
|
||
|
||
UserName - Supplies the username.
|
||
|
||
Password - Supplies the password.
|
||
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
NTSTATUS ntstatus;
|
||
NTSTATUS AuthPackageStatus;
|
||
|
||
STRING InputString;
|
||
LSA_OPERATIONAL_MODE SecurityMode = 0;
|
||
|
||
HANDLE LsaHandle;
|
||
|
||
ULONG AuthPackageId;
|
||
|
||
NWAUTH_SET_CREDENTIAL_REQUEST SetCredRequest;
|
||
PCHAR DummyOutput;
|
||
ULONG DummyOutputLength;
|
||
|
||
UNICODE_STRING PasswordStr;
|
||
UCHAR EncodeSeed = NW_ENCODE_SEED;
|
||
|
||
|
||
//
|
||
// Register this process as a logon process so that we can call
|
||
// NetWare authentication package.
|
||
//
|
||
RtlInitString(&InputString, "Microsoft NetWare Credential Manager");
|
||
|
||
ntstatus = LsaRegisterLogonProcess(
|
||
&InputString,
|
||
&LsaHandle,
|
||
&SecurityMode
|
||
);
|
||
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: NwpSetCredential: LsaRegisterLogonProcess returns x%08lx\n",
|
||
ntstatus));
|
||
return RtlNtStatusToDosError(ntstatus);
|
||
}
|
||
|
||
//
|
||
// Look up the NetWare authentication package
|
||
//
|
||
RtlInitString(&InputString, NW_AUTH_PACKAGE_NAME);
|
||
|
||
ntstatus = LsaLookupAuthenticationPackage(
|
||
LsaHandle,
|
||
&InputString,
|
||
&AuthPackageId
|
||
);
|
||
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: NwpSetCredential: LsaLookupAuthenticationPackage returns x%08lx\n",
|
||
ntstatus));
|
||
status = RtlNtStatusToDosError(ntstatus);
|
||
goto CleanExit;
|
||
}
|
||
|
||
//
|
||
// Ask authentication package for user information.
|
||
//
|
||
SetCredRequest.MessageType = NwAuth_SetCredential;
|
||
RtlCopyLuid(&SetCredRequest.LogonId, LogonId);
|
||
wcscpy(SetCredRequest.UserName, UserName);
|
||
wcscpy(SetCredRequest.Password, Password);
|
||
|
||
//
|
||
// Encode the password.
|
||
//
|
||
RtlInitUnicodeString(&PasswordStr, SetCredRequest.Password);
|
||
RtlRunEncodeUnicodeString(&EncodeSeed, &PasswordStr);
|
||
|
||
ntstatus = LsaCallAuthenticationPackage(
|
||
LsaHandle,
|
||
AuthPackageId,
|
||
&SetCredRequest,
|
||
sizeof(SetCredRequest),
|
||
(PVOID *) &DummyOutput,
|
||
&DummyOutputLength,
|
||
&AuthPackageStatus
|
||
);
|
||
|
||
if (NT_SUCCESS(ntstatus)) {
|
||
ntstatus = AuthPackageStatus;
|
||
}
|
||
if (! NT_SUCCESS(ntstatus)) {
|
||
KdPrint(("NWPROVAU: NwpSetCredential: LsaCallAuthenticationPackage returns x%08lx\n",
|
||
ntstatus));
|
||
status = RtlNtStatusToDosError(ntstatus);
|
||
}
|
||
else {
|
||
status = NO_ERROR;
|
||
}
|
||
|
||
CleanExit:
|
||
(void) LsaDeregisterLogonProcess(LsaHandle);
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS NwNdsOpenRdrHandle(
|
||
OUT PHANDLE phNwRdrHandle
|
||
)
|
||
{
|
||
|
||
NTSTATUS ntstatus;
|
||
IO_STATUS_BLOCK IoStatusBlock;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
ACCESS_MASK DesiredAccess = SYNCHRONIZE | GENERIC_READ;
|
||
|
||
WCHAR NameStr[] = L"\\Device\\NwRdr\\*";
|
||
UNICODE_STRING uOpenName;
|
||
|
||
//
|
||
// Prepare the open name.
|
||
//
|
||
|
||
RtlInitUnicodeString( &uOpenName, NameStr );
|
||
|
||
//
|
||
// Set up the object attributes.
|
||
//
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&uOpenName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL );
|
||
|
||
ntstatus = NtOpenFile(
|
||
phNwRdrHandle,
|
||
DesiredAccess,
|
||
&ObjectAttributes,
|
||
&IoStatusBlock,
|
||
FILE_SHARE_VALID_FLAGS,
|
||
FILE_SYNCHRONOUS_IO_NONALERT );
|
||
|
||
if ( !NT_ERROR(ntstatus) &&
|
||
!NT_INFORMATION(ntstatus) &&
|
||
!NT_WARNING(ntstatus)) {
|
||
|
||
return IoStatusBlock.Status;
|
||
|
||
}
|
||
|
||
return ntstatus;
|
||
}
|
||
|
||
VOID
|
||
NwpSelectServers(
|
||
IN HWND DialogHandle,
|
||
IN PCHANGE_PW_DLG_PARAM Credential
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays the dialog for user to select individual trees
|
||
to change password on. It then changes the password on the selected
|
||
list. After the password has been changed, it displays a dialog which lists
|
||
the 3.X bindery servers where the change could not be made.
|
||
|
||
Arguments:
|
||
|
||
DialogHandle - Supplies the handle to display dialog.
|
||
|
||
Credential - Provides on input the old and new passwords, and
|
||
the logged in user's name. Other field are ignored
|
||
on input and consecuently used within this function.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
INT_PTR Result;
|
||
|
||
Credential->TreeList = NULL;
|
||
Credential->UserList = NULL;
|
||
Credential->Entries = 0;
|
||
Credential->ChangedOne = FALSE;
|
||
|
||
Result = DialogBoxParamW( hmodNW,
|
||
MAKEINTRESOURCEW(DLG_PW_SELECT_SERVERS),
|
||
(HWND) DialogHandle,
|
||
(DLGPROC) NwpSelectServersDlgProc,
|
||
(LPARAM) Credential );
|
||
|
||
if ( Result == IDOK )
|
||
{
|
||
//
|
||
// Display list of trees (if any) for which password was changed.
|
||
//
|
||
DialogBoxParamW( hmodNW,
|
||
MAKEINTRESOURCEW(DLG_PW_CHANGED),
|
||
(HWND) DialogHandle,
|
||
(DLGPROC) NwpChangePasswordSuccessDlgProc,
|
||
(LPARAM) Credential );
|
||
|
||
if ( Credential->TreeList != NULL )
|
||
{
|
||
LocalFree( Credential->TreeList );
|
||
}
|
||
|
||
//
|
||
// Display a dialog to tell users to use SetPass if they have an
|
||
// account on a NetWare 3.X server.
|
||
//
|
||
NwpMessageBoxError( DialogHandle,
|
||
IDS_NETWARE_TITLE,
|
||
IDS_CHANGE_PASSWORD_INFO,
|
||
0,
|
||
NULL,
|
||
MB_OK );
|
||
}
|
||
}
|