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

1110 lines
29 KiB

/*++
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( &parameters->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( &parameters->BufLen ) <= NetpUnicodeToDBCSLen( dcName )) {
status = NERR_BufTooSmall;
} else {
NetpCopyWStrToStrDBCS( (LPSTR)XsSmbGetPointer( &parameters->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( &parameters->BufLen, (USHORT)( STRLEN( dcName ) + 1 ));
} else {
SmbPutUshort( &parameters->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( &parameters->Level ),
SmbGetUshort( &parameters->BufLen )));
}
try {
//
// Check for errors.
//
if (( SmbGetUshort( &parameters->Level ) != 0 )
&& ( SmbGetUshort( &parameters->Level ) != 2 )) {
Header->Status = ERROR_INVALID_LEVEL;
goto cleanup;
}
//
// Make the local call.
//
#ifdef LOGON_ENUM_SUPPORTED
status = NetLogonEnum(
NULL,
(DWORD)SmbGetUshort( &parameters->Level ),
(LPBYTE *)&outBuffer,
XsNativeBufferSize( SmbGetUshort( &parameters->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( &parameters->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( &parameters->Buffer ),
(LPVOID)XsSmbGetPointer( &parameters->Buffer ),
SmbGetUshort( &parameters->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( &parameters->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( &parameters->Buffer ),
SmbGetUshort( &parameters->BufLen ),
StructureDesc,
entriesFilled
);
}
//
// Set up the response parameters.
//
SmbPutUshort( &parameters->EntriesRead, (WORD)entriesFilled );
SmbPutUshort( &parameters->TotalAvail, (WORD)totalEntries );
cleanup:
;
} except ( EXCEPTION_EXECUTE_HANDLER ) {
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
}
NetApiBufferFree( outBuffer );
//
// Determine return buffer size.
//
XsSetDataCount(
&parameters->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( &parameters->Requestor )
);
//
// Copy the source credential, and zero out the destination
// credential.
//
RtlCopyMemory(
&inCredential,
(PVOID)XsSmbGetPointer( &parameters->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( &parameters->Requestor )
);
//
// Copy the source authenticator and password, and zero out the
// destination authenticator.
//
structure = (LPBYTE)XsSmbGetPointer( &parameters->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( &parameters->Requestor )
);
//
// Copy the source challenge, and zero out the destination
// challenge.
//
RtlCopyMemory(
&inChallenge,
(PVOID)XsSmbGetPointer( &parameters->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( &parameters->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( &parameters->OutBuf )
+ SmbGetUshort( &parameters->OutBufLen ) );
status = RapConvertSingleEntry(
(LPBYTE)&buffer,
Desc32_user_logoff_info_1,
FALSE,
(LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
(LPBYTE)XsSmbGetPointer( &parameters->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( &parameters->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( &parameters->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( &parameters->OutBufLen )) {
IF_DEBUG(ERRORS) {
NetpKdPrint(( "XsNetWkstaUserLogoff: More data available.\n" ));
}
Header->Status = ERROR_MORE_DATA;
}
if ( SmbGetUshort( &parameters->OutBufLen ) > sizeof(WORD)) {
logoffInfo = (PUSER_16_LOGOFF_INFO_1)XsSmbGetPointer(
&parameters->OutBuf );
SmbPutUshort( &logoffInfo->usrlogf1_code, VALID_LOGOFF );
}
//
// Set up the response parameters.
//
SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
cleanup:
;
} except ( EXCEPTION_EXECUTE_HANDLER ) {
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
}
NetpMemoryFree( userName );
NetpMemoryFree( machineName );
//
// Determine return buffer size.
//
XsSetDataCount(
&parameters->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( &parameters->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( &parameters->OutBuf )
+ SmbGetUshort( &parameters->OutBufLen ) );
status = RapConvertSingleEntry(
(LPBYTE)buffer,
Desc32_user_logon_info_1,
FALSE,
(LPBYTE)XsSmbGetPointer( &parameters->OutBuf ),
(LPBYTE)XsSmbGetPointer( &parameters->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( &parameters->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( &parameters->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( &parameters->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( &parameters->OutBuf ),
SmbGetUshort( &parameters->OutBufLen ),
Desc16_user_logon_info_1,
1
);
}
if ( SmbGetUshort( &parameters->OutBufLen ) > sizeof(WORD)) {
logonInfo = (PUSER_16_LOGON_INFO_1)XsSmbGetPointer(
&parameters->OutBuf );
SmbPutUshort( &logonInfo->usrlog1_code, VALIDATED_LOGON );
}
//
// Set up the response parameters.
//
SmbPutUshort( &parameters->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(
&parameters->OutBufLen,
Desc16_user_logon_info_1,
Header->Converter,
1,
Header->Status
);
return STATUS_SUCCESS;
} // XsNetWkstaUserLogon