windows-nt/Source/XPSP1/NT/ds/security/protocols/msv_sspi/msvwow.cxx

921 lines
27 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#if _WIN64
#include <global.h>
#include "msp.h"
#include "nlp.h"
#include "msvwow.h"
#define RELOCATE_WOW_UNICODE_STRING(WOWString, NativeString, Offset) \
NativeString.Length = WOWString.Length; \
NativeString.MaximumLength = WOWString.MaximumLength; \
NativeString.Buffer = (LPWSTR) ((LPBYTE) UlongToPtr(WOWString.Buffer) + Offset);
#define RELOCATE_WOW_ANSI_STRING(WOWString, NativeString, Offset) \
NativeString.Length = WOWString.Length; \
NativeString.MaximumLength = WOWString.MaximumLength; \
NativeString.Buffer = (LPSTR) ((LPBYTE) UlongToPtr(WOWString.Buffer) + Offset);
//+-------------------------------------------------------------------------
//
// Function: MsvPutWOWString
//
// Synopsis: Copies a UNICODE_STRING into a buffer
//
// Effects:
//
// Arguments: InputString - String to 'put'
// OutputString - Receives 'put' string
// Offset - Difference in addresses of local and client buffers.
// Where - Location in local buffer to place string.
//
// Requires:
//
// Returns:
//
// Notes: This code is (effectively) duplicated in
// KerbPutString. Make sure any changes
// made here are applied there as well.
//
//--------------------------------------------------------------------------
VOID
MsvPutWOWString(
IN PUNICODE_STRING InputString,
OUT PUNICODE_STRING_WOW64 OutputString,
IN LONG_PTR Offset,
IN OUT PBYTE * Where
)
{
OutputString->Length = OutputString->MaximumLength = InputString->Length;
OutputString->Buffer = PtrToUlong (*Where + Offset);
RtlCopyMemory(
*Where,
InputString->Buffer,
InputString->Length
);
*Where += InputString->Length;
}
//+-------------------------------------------------------------------------
//
// Function: MsvPutWOWClientString
//
// Synopsis: Copies a string into a buffer that will be copied to the
// 32-bit client's address space
//
// Effects:
//
// Arguments: Where - Location in local buffer to place string.
// OutString - Receives 'put' string
// InString - String to 'put'
//
// Requires:
//
// Returns:
//
// Notes: This code is (effectively) duplicated in
// KerbPutClientString. Make sure any changes
// made here are applied there as well.
//
//--------------------------------------------------------------------------
VOID
MsvPutWOWClientString(
IN OUT PCLIENT_BUFFER_DESC ClientBufferDesc,
IN PUNICODE_STRING_WOW64 OutString,
IN PUNICODE_STRING InString
)
/*++
Routine Description:
This routine copies the InString string to the memory pointed to by
ClientBufferDesc->StringOffset, and fixes the OutString string to point
to that new copy.
Parameters:
ClientBufferDesc - Descriptor of a buffer allocated in the client's
address space.
InString - A pointer to an NT string to be copied
OutString - A pointer to a destination NT string. This string structure
is in the "Mirror" allocated buffer.
Return Status:
STATUS_SUCCESS - Indicates the service completed successfully.
--*/
{
//
// Ensure our caller passed good data.
//
ASSERT( OutString != NULL );
ASSERT( InString != NULL );
ASSERT( COUNT_IS_ALIGNED( ClientBufferDesc->StringOffset, sizeof(WCHAR)) );
ASSERT( (LPBYTE)OutString >= ClientBufferDesc->MsvBuffer );
ASSERT( (LPBYTE)OutString <
ClientBufferDesc->MsvBuffer + ClientBufferDesc->TotalSize - sizeof(UNICODE_STRING) );
ASSERT( ClientBufferDesc->StringOffset + InString->Length + sizeof(WCHAR) <=
ClientBufferDesc->TotalSize );
#ifdef notdef
KdPrint(("NlpPutClientString: %ld %Z\n", InString->Length, InString ));
KdPrint((" Orig: UserBuffer: %lx Offset: 0x%lx TotalSize: 0x%lx\n",
ClientBufferDesc->UserBuffer,
ClientBufferDesc->StringOffset,
ClientBufferDesc->TotalSize ));
#endif
//
// Build a string structure and copy the text to the Mirror buffer.
//
if ( InString->Length > 0 ) {
ULONG_PTR TmpPtr;
//
// Copy the string (Add a zero character)
//
RtlCopyMemory(
ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset,
InString->Buffer,
InString->Length );
// Do one byte at a time since some callers don't pass in an even
// InString->Length
*(ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset +
InString->Length) = '\0';
*(ClientBufferDesc->MsvBuffer + ClientBufferDesc->StringOffset +
InString->Length+1) = '\0';
//
// Build the string structure to point to the data in the client's
// address space.
//
TmpPtr = (ULONG_PTR)(ClientBufferDesc->UserBuffer +
ClientBufferDesc->StringOffset);
OutString->Buffer = (ULONG)TmpPtr;
OutString->Length = InString->Length;
OutString->MaximumLength = OutString->Length + sizeof(WCHAR);
//
// Adjust the offset to past the newly copied string.
//
ClientBufferDesc->StringOffset += OutString->MaximumLength;
} else {
ZeroMemory( OutString, sizeof(*OutString) );
}
return;
}
//+-------------------------------------------------------------------------
//
// Function: MsvConvertWOWInteractiveLogonBuffer
//
// Synopsis: Converts logon buffers passed in from WOW clients to 64-bit
//
// Effects:
//
// Arguments: ProtocolSubmitBuffer -- original 32-bit logon buffer
// pSubmitBufferSize -- size of the 32-bit logon buffer
// MessageType -- format of the logon buffer
// ppTempSubmitBuffer -- filled in with the converted buffer
//
// Requires:
//
// Returns:
//
// Notes: This routine allocates the converted buffer and returns it
// on success. It is the caller's responsibility to free it.
//
//
//--------------------------------------------------------------------------
NTSTATUS
MsvConvertWOWInteractiveLogonBuffer(
IN PVOID ProtocolSubmitBuffer,
IN PVOID ClientBufferBase,
IN OUT PULONG pSubmitBufferSize,
OUT PVOID *ppTempSubmitBuffer
)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID pTempBuffer = NULL;
ULONG dwBufferSize = *pSubmitBufferSize;
PMSV1_0_INTERACTIVE_LOGON Logon;
PMSV1_0_INTERACTIVE_LOGON_WOW64 LogonWOW;
DWORD dwOffset;
DWORD dwWOWOffset;
//
// Pacify the compiler
//
UNREFERENCED_PARAMETER(ClientBufferBase);
//
// Scale up the size and add on 3 PVOIDs for the worst-case
// scenario to align the three embedded UNICODE_STRINGs
//
dwBufferSize += sizeof(MSV1_0_INTERACTIVE_LOGON)
- sizeof(MSV1_0_INTERACTIVE_LOGON_WOW64);
if (dwBufferSize < sizeof(MSV1_0_INTERACTIVE_LOGON))
{
#if 0
DebugLog((DEB_ERROR,
"Submit buffer to logon too small: %d. %ws, line %d\n",
dwBufferSize,
THIS_FILE,
__LINE__));
#endif
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
pTempBuffer = NtLmAllocatePrivateHeap(dwBufferSize);
if (pTempBuffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
Logon = (PMSV1_0_INTERACTIVE_LOGON) pTempBuffer;
LogonWOW = (PMSV1_0_INTERACTIVE_LOGON_WOW64) ProtocolSubmitBuffer;
Logon->MessageType = LogonWOW->MessageType;
dwOffset = sizeof(MSV1_0_INTERACTIVE_LOGON);
dwWOWOffset = sizeof(MSV1_0_INTERACTIVE_LOGON_WOW64);
//
// Copy the variable-length data
//
RtlCopyMemory((LPBYTE) Logon + dwOffset,
(LPBYTE) LogonWOW + dwWOWOffset,
*pSubmitBufferSize - dwWOWOffset);
//
// Set up the pointers in the native struct
//
RELOCATE_WOW_UNICODE_STRING(LogonWOW->LogonDomainName,
Logon->LogonDomainName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(LogonWOW->UserName,
Logon->UserName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(LogonWOW->Password,
Logon->Password,
dwOffset - dwWOWOffset);
*pSubmitBufferSize = dwBufferSize;
*ppTempSubmitBuffer = pTempBuffer;
return STATUS_SUCCESS;
Cleanup:
ASSERT(!NT_SUCCESS(Status));
if (pTempBuffer)
{
NtLmFreePrivateHeap(pTempBuffer);
}
return Status;
}
NTSTATUS
MsvConvertWOWNetworkLogonBuffer(
IN PVOID ProtocolSubmitBuffer,
IN PVOID ClientBufferBase,
IN OUT PULONG pSubmitBufferSize,
OUT PVOID *ppTempSubmitBuffer
)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID pTempBuffer = NULL;
ULONG dwBufferSize = *pSubmitBufferSize;
PMSV1_0_LM20_LOGON Logon;
PMSV1_0_LM20_LOGON_WOW64 LogonWOW;
DWORD dwOffset;
DWORD dwWOWOffset;
//
// Pacify the compiler
//
UNREFERENCED_PARAMETER(ClientBufferBase);
//
// Scale up the size and add on 5 PVOIDs for the worst-case
// scenario to align the three embedded UNICODE_STRINGs
//
dwBufferSize += sizeof(MSV1_0_LM20_LOGON)
- sizeof(MSV1_0_LM20_LOGON_WOW64);
if (dwBufferSize < sizeof(MSV1_0_LM20_LOGON))
{
#if 0
DebugLog((DEB_ERROR,
"Submit buffer to logon too small: %d. %ws, line %d\n",
dwBufferSize,
THIS_FILE,
__LINE__));
#endif
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
pTempBuffer = NtLmAllocatePrivateHeap(dwBufferSize);
if (pTempBuffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
Logon = (PMSV1_0_LM20_LOGON) pTempBuffer;
LogonWOW = (PMSV1_0_LM20_LOGON_WOW64) ProtocolSubmitBuffer;
//
// copy fixed fields.
//
Logon->MessageType = LogonWOW->MessageType;
Logon->ParameterControl = LogonWOW->ParameterControl;
RtlCopyMemory(Logon->ChallengeToClient, LogonWOW->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
dwOffset = sizeof(MSV1_0_LM20_LOGON);
dwWOWOffset = sizeof(MSV1_0_LM20_LOGON_WOW64);
//
// Copy the variable-length data
//
RtlCopyMemory((LPBYTE) Logon + dwOffset,
(LPBYTE) LogonWOW + dwWOWOffset,
*pSubmitBufferSize - dwWOWOffset);
//
// Set up the pointers in the native struct
//
RELOCATE_WOW_UNICODE_STRING(LogonWOW->LogonDomainName,
Logon->LogonDomainName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(LogonWOW->UserName,
Logon->UserName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(LogonWOW->Workstation,
Logon->Workstation,
dwOffset - dwWOWOffset);
RELOCATE_WOW_ANSI_STRING(LogonWOW->CaseSensitiveChallengeResponse,
Logon->CaseSensitiveChallengeResponse,
dwOffset - dwWOWOffset);
RELOCATE_WOW_ANSI_STRING(LogonWOW->CaseInsensitiveChallengeResponse,
Logon->CaseInsensitiveChallengeResponse,
dwOffset - dwWOWOffset);
*pSubmitBufferSize = dwBufferSize;
*ppTempSubmitBuffer = pTempBuffer;
return STATUS_SUCCESS;
Cleanup:
ASSERT(!NT_SUCCESS(Status));
if (pTempBuffer)
{
NtLmFreePrivateHeap(pTempBuffer);
}
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: MsvConvertWOWChangePasswordBuffer
//
// Synopsis: Converts change password buffers passed in from
// WOW clients to 64-bit
//
// Effects:
//
// Arguments: ProtocolSubmitBuffer -- original 32-bit buffer
// ClientBufferBase -- base address
// pSubmitBufferSize -- size of the 32-bit buffer
// ppTempSubmitBuffer -- filled in with the converted buffer
//
// Requires:
//
// Returns:
//
// Notes: This routine allocates the converted buffer and returns it
// on success. It is the caller's responsibility to free it.
//
//
//--------------------------------------------------------------------------
NTSTATUS
MsvConvertWOWChangePasswordBuffer(
IN PVOID ProtocolSubmitBuffer,
IN PVOID ClientBufferBase,
IN OUT PULONG pSubmitBufferSize,
OUT PVOID *ppTempSubmitBuffer
)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID pTempBuffer = NULL;
ULONG dwBufferSize = *pSubmitBufferSize;
PMSV1_0_CHANGEPASSWORD_REQUEST PasswordRequest;
PMSV1_0_CHANGEPASSWORD_REQUEST_WOW64 PasswordRequestWOW;
DWORD dwOffset;
DWORD dwWOWOffset;
//
// Pacify the compiler
//
UNREFERENCED_PARAMETER(ClientBufferBase);
//
// Scale up the size
//
dwBufferSize += sizeof(MSV1_0_CHANGEPASSWORD_REQUEST)
- sizeof(MSV1_0_CHANGEPASSWORD_REQUEST_WOW64);
if (dwBufferSize < sizeof(MSV1_0_CHANGEPASSWORD_REQUEST))
{
#if 0
DebugLog((DEB_ERROR,
"Submit buffer to logon too small: %d. %ws, line %d\n",
dwBufferSize,
THIS_FILE,
__LINE__));
#endif
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
pTempBuffer = NtLmAllocatePrivateHeap(dwBufferSize);
if (pTempBuffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
PasswordRequest = (PMSV1_0_CHANGEPASSWORD_REQUEST) pTempBuffer;
PasswordRequestWOW = (PMSV1_0_CHANGEPASSWORD_REQUEST_WOW64) ProtocolSubmitBuffer;
//
// copy fixed fields.
//
PasswordRequest->MessageType = PasswordRequestWOW->MessageType;
PasswordRequest->Impersonating = PasswordRequestWOW->Impersonating;
dwOffset = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST);
dwWOWOffset = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST_WOW64);
//
// Copy the variable-length data
//
RtlCopyMemory((LPBYTE) PasswordRequest + dwOffset,
(LPBYTE) PasswordRequestWOW + dwWOWOffset,
*pSubmitBufferSize - dwWOWOffset);
//
// Set up the pointers in the native struct
//
RELOCATE_WOW_UNICODE_STRING(PasswordRequestWOW->DomainName,
PasswordRequest->DomainName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(PasswordRequestWOW->AccountName,
PasswordRequest->AccountName,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(PasswordRequestWOW->OldPassword,
PasswordRequest->OldPassword,
dwOffset - dwWOWOffset);
RELOCATE_WOW_UNICODE_STRING(PasswordRequestWOW->NewPassword,
PasswordRequest->NewPassword,
dwOffset - dwWOWOffset);
*pSubmitBufferSize = dwBufferSize;
*ppTempSubmitBuffer = pTempBuffer;
return STATUS_SUCCESS;
Cleanup:
ASSERT(!NT_SUCCESS(Status));
if (pTempBuffer)
{
NtLmFreePrivateHeap(pTempBuffer);
}
return Status;
}
NTSTATUS
MsvAllocateInteractiveWOWProfile (
IN PLSA_CLIENT_REQUEST ClientRequest,
OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
OUT PULONG ProfileBufferSize,
IN PNETLOGON_VALIDATION_SAM_INFO4 NlpUser
)
/*++
Routine Description:
This allocates and fills in the clients interactive profile.
Arguments:
ClientRequest - Is a pointer to an opaque data structure
representing the client's request.
ProfileBuffer - Is used to return the address of the profile
buffer in the client process. This routine is
responsible for allocating and returning the profile buffer
within the client process. However, if the caller subsequently
encounters an error which prevents a successful logon, then
then it will take care of deallocating the buffer. This
buffer is allocated with the AllocateClientBuffer() service.
ProfileBufferSize - Receives the Size (in bytes) of the
returned profile buffer.
NlpUser - Contains the validation information which is
to be copied in the ProfileBuffer.
Return Value:
STATUS_SUCCESS - Indicates the service completed successfully.
STATUS_QUOTA_EXCEEDED - This error indicates that the logon
could not be completed because the client does not have
sufficient quota to allocate the return buffer.
--*/
{
NTSTATUS Status;
CLIENT_BUFFER_DESC ClientBufferDesc;
PMSV1_0_INTERACTIVE_PROFILE_WOW64 LocalProfileBuffer;
//
// Alocate the profile buffer to return to the client
//
NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
*ProfileBuffer = NULL;
*ProfileBufferSize = sizeof(MSV1_0_INTERACTIVE_PROFILE_WOW64) +
NlpUser->LogonScript.Length + sizeof(WCHAR) +
NlpUser->HomeDirectory.Length + sizeof(WCHAR) +
NlpUser->HomeDirectoryDrive.Length + sizeof(WCHAR) +
NlpUser->FullName.Length + sizeof(WCHAR) +
NlpUser->ProfilePath.Length + sizeof(WCHAR) +
NlpUser->LogonServer.Length + sizeof(WCHAR);
Status = NlpAllocateClientBuffer( &ClientBufferDesc,
sizeof(MSV1_0_INTERACTIVE_PROFILE_WOW64),
*ProfileBufferSize );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
LocalProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE_WOW64) ClientBufferDesc.MsvBuffer;
//
// Copy the scalar fields into the profile buffer.
//
LocalProfileBuffer->MessageType = MsV1_0InteractiveProfile;
LocalProfileBuffer->LogonCount = NlpUser->LogonCount;
LocalProfileBuffer->BadPasswordCount= NlpUser->BadPasswordCount;
OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogonTime,
LocalProfileBuffer->LogonTime );
OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogoffTime,
LocalProfileBuffer->LogoffTime );
OLD_TO_NEW_LARGE_INTEGER( NlpUser->KickOffTime,
LocalProfileBuffer->KickOffTime );
OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordLastSet,
LocalProfileBuffer->PasswordLastSet );
OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordCanChange,
LocalProfileBuffer->PasswordCanChange );
OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordMustChange,
LocalProfileBuffer->PasswordMustChange );
LocalProfileBuffer->UserFlags = NlpUser->UserFlags;
//
// Copy the Unicode strings into the profile buffer.
//
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->LogonScript,
&NlpUser->LogonScript );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->HomeDirectory,
&NlpUser->HomeDirectory );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->HomeDirectoryDrive,
&NlpUser->HomeDirectoryDrive );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->FullName,
&NlpUser->FullName );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->ProfilePath,
&NlpUser->ProfilePath );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfileBuffer->LogonServer,
&NlpUser->LogonServer );
//
// Flush the buffer to the client's address space.
//
Status = NlpFlushClientBuffer( &ClientBufferDesc,
(PVOID *) ProfileBuffer );
Cleanup:
//
// If the copy wasn't successful,
// cleanup resources we would have returned to the caller.
//
if ( !NT_SUCCESS(Status) ) {
NlpFreeClientBuffer( &ClientBufferDesc );
}
return Status;
}
NTSTATUS
MsvAllocateNetworkWOWProfile (
IN PLSA_CLIENT_REQUEST ClientRequest,
OUT PMSV1_0_LM20_LOGON_PROFILE *ProfileBuffer,
OUT PULONG ProfileBufferSize,
IN PNETLOGON_VALIDATION_SAM_INFO4 NlpUser,
IN ULONG ParameterControl
)
/*++
Routine Description:
This allocates and fills in the clients network profile.
Arguments:
ClientRequest - Is a pointer to an opaque data structure
representing the client's request.
ProfileBuffer - Is used to return the address of the profile
buffer in the client process. This routine is
responsible for allocating and returning the profile buffer
within the client process. However, if the caller subsequently
encounters an error which prevents a successful logon, then
then it will take care of deallocating the buffer. This
buffer is allocated with the AllocateClientBuffer() service.
ProfileBufferSize - Receives the Size (in bytes) of the
returned profile buffer.
NlpUser - Contains the validation information which is
to be copied in the ProfileBuffer. Will be NULL to indicate a
NULL session.
Return Value:
STATUS_SUCCESS - Indicates the service completed successfully.
STATUS_QUOTA_EXCEEDED - This error indicates that the logon
could not be completed because the client does not have
sufficient quota to allocate the return buffer.
--*/
{
NTSTATUS Status;
NTSTATUS SubAuthStatus = STATUS_SUCCESS;
CLIENT_BUFFER_DESC ClientBufferDesc;
PMSV1_0_LM20_LOGON_PROFILE_WOW64 LocalProfile;
//
// Alocate the profile buffer to return to the client
//
NlpInitClientBuffer( &ClientBufferDesc, ClientRequest );
*ProfileBuffer = NULL;
*ProfileBufferSize = sizeof(MSV1_0_LM20_LOGON_PROFILE_WOW64);
if ( NlpUser != NULL ) {
*ProfileBufferSize += NlpUser->LogonDomainName.Length + sizeof(WCHAR) +
NlpUser->LogonServer.Length + sizeof(WCHAR) +
NlpUser->HomeDirectoryDrive.Length + sizeof(WCHAR);
}
Status = NlpAllocateClientBuffer( &ClientBufferDesc,
sizeof(MSV1_0_LM20_LOGON_PROFILE_WOW64),
*ProfileBufferSize );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
LocalProfile = (PMSV1_0_LM20_LOGON_PROFILE_WOW64) ClientBufferDesc.MsvBuffer;
LocalProfile->MessageType = MsV1_0Lm20LogonProfile;
//
// For a NULL session, return a constant profile buffer
//
if ( NlpUser == NULL ) {
LocalProfile->KickOffTime.HighPart = 0x7FFFFFFF;
LocalProfile->KickOffTime.LowPart = 0xFFFFFFFF;
LocalProfile->LogoffTime.HighPart = 0x7FFFFFFF;
LocalProfile->LogoffTime.LowPart = 0xFFFFFFFF;
LocalProfile->UserFlags = 0;
RtlZeroMemory( LocalProfile->UserSessionKey,
sizeof(LocalProfile->UserSessionKey));
RtlZeroMemory( LocalProfile->LanmanSessionKey,
sizeof(LocalProfile->LanmanSessionKey));
RtlZeroMemory( &LocalProfile->LogonDomainName, sizeof(LocalProfile->LogonDomainName) );
RtlZeroMemory( &LocalProfile->LogonServer, sizeof(LocalProfile->LogonServer) );
RtlZeroMemory( &LocalProfile->UserParameters, sizeof(LocalProfile->UserParameters) );
//
// For non-null sessions,
// fill in the profile buffer.
//
} else {
//
// Copy the individual scalar fields into the profile buffer.
//
if ((ParameterControl & MSV1_0_RETURN_PASSWORD_EXPIRY) != 0) {
OLD_TO_NEW_LARGE_INTEGER( NlpUser->PasswordMustChange,
LocalProfile->LogoffTime);
} else {
OLD_TO_NEW_LARGE_INTEGER( NlpUser->LogoffTime,
LocalProfile->LogoffTime);
}
OLD_TO_NEW_LARGE_INTEGER( NlpUser->KickOffTime,
LocalProfile->KickOffTime);
LocalProfile->UserFlags = NlpUser->UserFlags;
RtlCopyMemory( LocalProfile->UserSessionKey,
&NlpUser->UserSessionKey,
sizeof(LocalProfile->UserSessionKey) );
ASSERT( SAMINFO_LM_SESSION_KEY_SIZE ==
sizeof(LocalProfile->LanmanSessionKey) );
RtlCopyMemory(
LocalProfile->LanmanSessionKey,
&NlpUser->ExpansionRoom[SAMINFO_LM_SESSION_KEY],
SAMINFO_LM_SESSION_KEY_SIZE );
// We need to extract the true status sent back for subauth users,
// but not by a sub auth package
SubAuthStatus = NlpUser->ExpansionRoom[SAMINFO_SUBAUTH_STATUS];
//
// Copy the Unicode strings into the profile buffer.
//
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfile->LogonDomainName,
&NlpUser->LogonDomainName );
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfile->LogonServer,
&NlpUser->LogonServer );
//
// Kludge: Pass back UserParameters in HomeDirectoryDrive since we
// can't change the NETLOGON_VALIDATION_SAM_INFO structure between
// releases NT 1.0 and NT 1.0A. HomeDirectoryDrive was NULL for release 1.0A
// so we'll use that field.
//
MsvPutWOWClientString( &ClientBufferDesc,
&LocalProfile->UserParameters,
&NlpUser->HomeDirectoryDrive );
}
//
// Flush the buffer to the client's address space.
//
Status = NlpFlushClientBuffer( &ClientBufferDesc,
(PVOID*)ProfileBuffer );
Cleanup:
//
// If the copy wasn't successful,
// cleanup resources we would have returned to the caller.
//
if ( !NT_SUCCESS(Status) ) {
NlpFreeClientBuffer( &ClientBufferDesc );
}
// Save the status for subauth logons
if (NT_SUCCESS(Status) && !NT_SUCCESS(SubAuthStatus))
{
Status = SubAuthStatus;
}
return Status;
}
#endif // _WIN64