|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ApiLogon.c
Abstract:
This module contains individual API handlers for the NetLogon APIs.
SUPPORTED : NetGetDCName, NetLogonEnum, NetServerAuthenticate, NetServerPasswordSet, NetServerReqChallenge, NetWkstaUserLogoff, NetWkstaUserLogon.
SEE ALSO : NetAccountDeltas, NetAccountSync - in ApiAcct.c.
Author:
Shanku Niyogi (w-shanku) 04-Apr-1991
Revision History:
--*/
//
// Logon APIs are Unicode only.
//
#ifndef UNICODE
#define UNICODE
#endif
#include "xactsrvp.h"
#include <netlibnt.h>
#include <crypt.h> // must be included before <logonmsv.h>
#include <ntsam.h> // must be included before <logonmsv.h>
#include <logonmsv.h> // must be included before <ssi.h>
#include <ssi.h> // I_NetAccountDeltas and I_NetAccountSync prototypes
//
// Declaration of descriptor strings.
//
STATIC const LPDESC Desc16_user_logon_info_0 = REM16_user_logon_info_0; STATIC const LPDESC Desc32_user_logon_info_0 = REM32_user_logon_info_0; STATIC const LPDESC Desc16_user_logon_info_1 = REM16_user_logon_info_1; STATIC const LPDESC Desc32_user_logon_info_1 = REM32_user_logon_info_1; STATIC const LPDESC Desc16_user_logon_info_2 = REM16_user_logon_info_2; STATIC const LPDESC Desc32_user_logon_info_2 = REM32_user_logon_info_2; STATIC const LPDESC Desc16_user_logoff_info_1 = REM16_user_logoff_info_1; STATIC const LPDESC Desc32_user_logoff_info_1 = REM32_user_logoff_info_1;
NTSTATUS XsNetGetDCName ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetGetDCName.
Arguments:
API_HANDLER_PARAMETERS - Information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ NET_API_STATUS status;
PXS_NET_GET_DC_NAME parameters = Parameters; LPTSTR nativeDomain = NULL; // Native parameters
LPTSTR dcName = NULL;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeDomain, (LPSTR)XsSmbGetPointer( ¶meters->Domain ) );
//
// Make the local call.
//
status = NetGetDCName( NULL, nativeDomain, (LPBYTE *)&dcName );
if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGetDCName: NetGetDCName failed: %X\n", status )); } goto cleanup; }
//
// Put string into buffer. Convert from Unicode if necessary.
//
if ( (DWORD)SmbGetUshort( ¶meters->BufLen ) <= NetpUnicodeToDBCSLen( dcName )) {
status = NERR_BufTooSmall;
} else {
NetpCopyWStrToStrDBCS( (LPSTR)XsSmbGetPointer( ¶meters->Buffer ), dcName );
}
IF_DEBUG(LOGON) { NetpKdPrint(( "Name is %ws\n", dcName )); }
cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Set return data count.
//
if ( status == NERR_Success ) { SmbPutUshort( ¶meters->BufLen, (USHORT)( STRLEN( dcName ) + 1 )); } else { SmbPutUshort( ¶meters->BufLen, 0 ); }
Header->Status = (WORD)status; NetpMemoryFree( nativeDomain ); NetApiBufferFree( dcName );
return STATUS_SUCCESS;
} // XsNetGetDCName
NTSTATUS XsNetLogonEnum ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetLogonEnum.
Arguments:
API_HANDLER_PARAMETERS - Information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ NET_API_STATUS status;
PXS_NET_LOGON_ENUM parameters = Parameters; LPVOID outBuffer= NULL; DWORD entriesRead = 0; DWORD totalEntries = 0;
DWORD entriesFilled = 0; DWORD bytesRequired = 0; LPDESC nativeStructureDesc;
API_HANDLER_PARAMETERS_REFERENCE;
IF_DEBUG(LOGON) { NetpKdPrint(( "XsNetLogonEnum: header at %lx, params at %lx, " "level %ld, buf size %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); }
try { //
// Check for errors.
//
if (( SmbGetUshort( ¶meters->Level ) != 0 ) && ( SmbGetUshort( ¶meters->Level ) != 2 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// Make the local call.
//
#ifdef LOGON_ENUM_SUPPORTED
status = NetLogonEnum( NULL, (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer, XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )), &entriesRead, &totalEntries, NULL ); #else // LOGON_ENUM_SUPPORTED
status = NERR_InvalidAPI; #endif // LOGON_ENUM_SUPPORTED
if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetLogonEnum: NetLogonEnum failed: " "%X\n", status )); } Header->Status = (WORD)status; goto cleanup; }
IF_DEBUG(LOGON) { NetpKdPrint(( "XsNetLogonEnum: received %ld entries at %lx\n", entriesRead, outBuffer )); }
//
// Use the requested level to determine the format of the
// data structure.
//
switch ( SmbGetUshort( ¶meters->Level ) ) {
case 0:
nativeStructureDesc = Desc32_user_logon_info_0; StructureDesc = Desc16_user_logon_info_0; break;
case 2:
nativeStructureDesc = Desc32_user_logon_info_2; StructureDesc = Desc16_user_logon_info_2; break; }
//
// Do the actual conversion from the 32-bit structures to 16-bit
// structures.
//
XsFillEnumBuffer( outBuffer, entriesRead, nativeStructureDesc, (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, NULL, // verify function
&bytesRequired, &entriesFilled, NULL );
IF_DEBUG(LOGON) { NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR," " Entries %ld of %ld\n", outBuffer, SmbGetUlong( ¶meters->Buffer ), bytesRequired, entriesFilled, totalEntries )); }
//
// If all the entries could not be filled, return ERROR_MORE_DATA,
// and return the buffer as is. Otherwise, the data needs to be
// packed so that we don't send too much useless data.
//
if ( entriesFilled < totalEntries ) {
Header->Status = ERROR_MORE_DATA;
} else {
Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, entriesFilled );
}
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled ); SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetApiBufferFree( outBuffer );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, entriesFilled, Header->Status );
return STATUS_SUCCESS;
} // XsNetLogonEnum
NTSTATUS XsNetServerAuthenticate ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetServerAuthenticate.
Arguments:
API_HANDLER_PARAMETERS - Information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ PXS_NET_SERVER_AUTHENTICATE parameters = Parameters; NET_API_STATUS status; // Native parameters
LPTSTR nativeRequestor = NULL; NETLOGON_CREDENTIAL inCredential = {0}; NETLOGON_CREDENTIAL outCredential = {0}; WCHAR AccountName[MAX_PATH+1];
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeRequestor, (LPSTR)XsSmbGetPointer( ¶meters->Requestor ) );
//
// Copy the source credential, and zero out the destination
// credential.
//
RtlCopyMemory( &inCredential, (PVOID)XsSmbGetPointer( ¶meters->Caller ), sizeof(NETLOGON_CREDENTIAL) );
RtlZeroMemory( &outCredential, sizeof(NETLOGON_CREDENTIAL) );
//
// Build the account name.
//
NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
//
// Make the local call.
//
status = NetpNtStatusToApiStatus( I_NetServerAuthenticate( NULL, AccountName, UasServerSecureChannel, nativeRequestor, &inCredential, &outCredential ));
if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetServerAuthenticate: I_NetServerAuthenticate " "failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; }
cleanup:
//
// Set the return credential.
//
RtlCopyMemory( parameters->Primary, &outCredential, sizeof(NETLOGON_CREDENTIAL) );
} except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetpMemoryFree( nativeRequestor );
return STATUS_SUCCESS;
} // XsNetServerAuthenticate
NTSTATUS XsNetServerPasswordSet ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetGetDCName.
Arguments:
API_HANDLER_PARAMETERS - Information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ PXS_NET_SERVER_PASSWORD_SET parameters = Parameters; NET_API_STATUS status; // Native parameters
LPTSTR nativeRequestor = NULL; NETLOGON_AUTHENTICATOR authIn = {0}; NETLOGON_AUTHENTICATOR authOut = {0}; ENCRYPTED_LM_OWF_PASSWORD password; WCHAR AccountName[MAX_PATH+1];
LPBYTE structure = NULL; // Conversion variables
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeRequestor, (LPSTR)XsSmbGetPointer( ¶meters->Requestor ) );
//
// Copy the source authenticator and password, and zero out the
// destination authenticator.
//
structure = (LPBYTE)XsSmbGetPointer( ¶meters->Authenticator ); RtlCopyMemory( &authIn.Credential, structure, sizeof(NETLOGON_CREDENTIAL) ); structure += sizeof(NETLOGON_CREDENTIAL); authIn.timestamp = SmbGetUlong( structure );
RtlCopyMemory( &password, parameters->Password, sizeof(ENCRYPTED_LM_OWF_PASSWORD) );
RtlZeroMemory( &authOut, sizeof(NETLOGON_CREDENTIAL) );
//
// Build the account name.
//
if( STRLEN( nativeRequestor ) >= MAX_PATH ) { Header->Status = NERR_PasswordTooShort; goto cleanup; }
// Make sure its NULL terminated
AccountName[MAX_PATH] = L'\0'; NetpNCopyTStrToWStr( AccountName, nativeRequestor, MAX_PATH );
//
// Make the local call.
//
status = NetpNtStatusToApiStatus( I_NetServerPasswordSet( NULL, AccountName, UasServerSecureChannel, nativeRequestor, &authIn, &authOut, &password ));
if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetServerPasswordSet: " "I_NetServerPasswordSet failed: %X\n", status )); }
//
// !!! When protocol level is available in the header information,
// we can check it. Right now, we ignore this code.
//
// For clients older than LanMan 2.1, return a different error code.
// LANMAN 2.1 Protocol Level is 6.
//
#if 0
if ( status == NERR_TimeDiffAtDC && Header->ProtocolLevel < 6 ) { status = NERR_SyncRequired; } #endif
Header->Status = (WORD)status; goto cleanup; }
cleanup:
//
// Fill in 16 bit return structures.
//
structure = parameters->RetAuth; RtlCopyMemory( structure, &authOut.Credential, sizeof(NETLOGON_CREDENTIAL) ); structure += sizeof(NETLOGON_CREDENTIAL); SmbPutUlong( (LPDWORD)structure, authOut.timestamp );
} except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetpMemoryFree( nativeRequestor );
return STATUS_SUCCESS;
} // XsNetServerPasswordSet
NTSTATUS XsNetServerReqChallenge ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetGetDCName.
Arguments:
API_HANDLER_PARAMETERS - Information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ PXS_NET_SERVER_REQ_CHALLENGE parameters = Parameters; NET_API_STATUS status; // Native parameters
LPTSTR nativeRequestor = NULL; NETLOGON_CREDENTIAL inChallenge = {0}; NETLOGON_CREDENTIAL outChallenge = {0};
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeRequestor, (LPSTR)XsSmbGetPointer( ¶meters->Requestor ) );
//
// Copy the source challenge, and zero out the destination
// challenge.
//
RtlCopyMemory( &inChallenge, (PVOID)XsSmbGetPointer( ¶meters->Caller ), sizeof(NETLOGON_CREDENTIAL) );
RtlZeroMemory( &outChallenge, sizeof(NETLOGON_CREDENTIAL) );
//
// Make the local call.
//
status = NetpNtStatusToApiStatus( I_NetServerReqChallenge( NULL, nativeRequestor, &inChallenge, &outChallenge ));
if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetServerReqChallenge: " "I_NetServerReqChallenge failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; }
cleanup:
//
// Set the return credential.
//
RtlCopyMemory( parameters->Primary, &outChallenge, sizeof(NETLOGON_CREDENTIAL) ); } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetpMemoryFree( nativeRequestor );
return STATUS_SUCCESS;
} // XsNetServerReqChallenge
NTSTATUS XsNetWkstaUserLogoff ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This temporary routine just returns STATUS_NOT_IMPLEMENTED.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ NET_API_STATUS status;
PXS_NET_WKSTA_USER_LOGOFF parameters = Parameters; LPWSTR machineName = NULL; // Native parameters
LPWSTR userName = NULL; NETLOGON_LOGOFF_UAS_INFORMATION buffer;
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; PWKSTA_16_USER_LOGOFF_REQUEST_1 usrLogoffReq = (PWKSTA_16_USER_LOGOFF_REQUEST_1)parameters->InBuf; PUSER_16_LOGOFF_INFO_1 logoffInfo;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertUnicodeTextParameter( userName, (LPSTR)( usrLogoffReq->wlreq1_name ) );
XsConvertUnicodeTextParameter( machineName, (LPSTR)( usrLogoffReq->wlreq1_workstation ) );
if ( SmbGetUshort( ¶meters->Level ) != 1 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// Make sure the workstation name in the logon request is the
// name of the workstation from which the request came.
//
if ( wcscmp( machineName, Header->ClientMachineName ) ) {
Header->Status = (WORD)ERROR_ACCESS_DENIED; goto cleanup; }
//
// Make the local call.
//
status = I_NetLogonUasLogoff( userName, machineName, &buffer );
if ( !XsApiSuccess(status)) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogoff: I_NetLogonUasLogoff " "failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; }
//
// Convert the structure returned by the 32-bit call to a 16-bit
// structure. The last possible location for variable data is
// calculated from buffer location and length.
//
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->OutBuf ) + SmbGetUshort( ¶meters->OutBufLen ) );
status = RapConvertSingleEntry( (LPBYTE)&buffer, Desc32_user_logoff_info_1, FALSE, (LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ), (LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ), Desc16_user_logoff_info_1, TRUE, &stringLocation, &bytesRequired, Response, NativeToRap );
if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogoff: RapConvertSingleEntry " "failed: %X\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
IF_DEBUG(LOGON) { NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n", &buffer, SmbGetUlong( ¶meters->OutBuf ), bytesRequired )); }
//
// Determine return code based on the size of the buffer.
// The user_logoff_info_1 structure has no variable data to pack,
// but we do need to fill in the code field of the return structure.
//
if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->OutBufLen ), Desc16_user_logoff_info_1, FALSE // not in native format
)) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogoff: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall;
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters->OutBufLen )) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" )); } Header->Status = ERROR_MORE_DATA; }
if ( SmbGetUshort( ¶meters->OutBufLen ) > sizeof(WORD)) {
logoffInfo = (PUSER_16_LOGOFF_INFO_1)XsSmbGetPointer( ¶meters->OutBuf ); SmbPutUshort( &logoffInfo->usrlogf1_code, VALID_LOGOFF ); }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetpMemoryFree( userName ); NetpMemoryFree( machineName );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->OutBufLen, Desc16_user_logoff_info_1, Header->Converter, 1, Header->Status );
return STATUS_SUCCESS;
} // XsNetWkstaUserLogoff
NTSTATUS XsNetWkstaUserLogon ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetWkstaUserLogon.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ NET_API_STATUS status; PXS_NET_WKSTA_USER_LOGON parameters = Parameters; LPWSTR machineName = NULL; // Native parameters
LPWSTR userName = NULL; PNETLOGON_VALIDATION_UAS_INFO buffer = NULL;
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; PWKSTA_16_USER_LOGON_REQUEST_1 usrLogonReq = (PWKSTA_16_USER_LOGON_REQUEST_1)parameters->InBuf; PUSER_16_LOGON_INFO_1 logonInfo;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
XsConvertUnicodeTextParameter( userName, (LPSTR)( usrLogonReq->wlreq1_name ) );
XsConvertUnicodeTextParameter( machineName, (LPSTR)( usrLogonReq->wlreq1_workstation ) );
if ( SmbGetUshort( ¶meters->Level ) != 1 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// Make sure the workstation name in the logon request is the
// name of the workstation from which the request came.
//
if ( wcscmp( machineName, Header->ClientMachineName ) ) {
Header->Status = (WORD)ERROR_ACCESS_DENIED; goto cleanup; }
//
// Make the local call.
//
status = I_NetLogonUasLogon( userName, machineName, &buffer );
if ( !XsApiSuccess ( status )) {
IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogon: I_NetLogonUasLogon failed: " "%X\n", status)); } Header->Status = (WORD) status; goto cleanup; }
//
// Convert the structure returned by the 32-bit call to a 16-bit
// structure. The last possible location for variable data is
// calculated from buffer location and length.
//
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->OutBuf ) + SmbGetUshort( ¶meters->OutBufLen ) );
status = RapConvertSingleEntry( (LPBYTE)buffer, Desc32_user_logon_info_1, FALSE, (LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ), (LPBYTE)XsSmbGetPointer( ¶meters->OutBuf ), Desc16_user_logon_info_1, TRUE, &stringLocation, &bytesRequired, Response, NativeToRap );
if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogon: RapConvertSingleEntry " "failed: %X\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
IF_DEBUG(LOGON) { NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n", buffer, SmbGetUlong( ¶meters->OutBuf ), bytesRequired )); }
//
// Determine return code based on the size of the buffer.
// The user_logoff_info_1 structure has no variable data to pack,
// but we do need to fill in the code field of the return structure.
//
if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->OutBufLen ), Desc16_user_logon_info_1, FALSE // not in native format
)) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogon: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall;
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters->OutBufLen )) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" )); } Header->Status = ERROR_MORE_DATA;
} else {
//
// Pack the response data.
//
Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->OutBuf ), SmbGetUshort( ¶meters->OutBufLen ), Desc16_user_logon_info_1, 1 ); }
if ( SmbGetUshort( ¶meters->OutBufLen ) > sizeof(WORD)) {
logonInfo = (PUSER_16_LOGON_INFO_1)XsSmbGetPointer( ¶meters->OutBuf ); SmbPutUshort( &logonInfo->usrlog1_code, VALIDATED_LOGON ); }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetpMemoryFree( userName ); NetpMemoryFree( machineName ); if ( buffer != NULL ) { NetApiBufferFree( buffer ); }
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->OutBufLen, Desc16_user_logon_info_1, Header->Converter, 1, Header->Status );
return STATUS_SUCCESS;
} // XsNetWkstaUserLogon
|