2025 lines
50 KiB
2025 lines
50 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
adtbuild.c
|
|
|
|
Abstract:
|
|
|
|
Local Security Authority - Audit Log Management
|
|
|
|
Functions in this module build unicode strings for
|
|
various parameter types. Some parameter string build
|
|
routines may also be found in other modules (such as
|
|
LsapAdtBuildAccessesString() in adtobjs.c).
|
|
|
|
Author:
|
|
|
|
Jim Kelly (JimK) 29-Oct-1992
|
|
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <lsapch2.h>
|
|
#include "adtp.h"
|
|
#include "wsautils.h"
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Local Macro definitions and local function prototypes //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
const LONGLONG ADT_DURATION_ONE_SEC = (LONGLONG)(10000000i64); // no of 100ns intervals per second
|
|
const LONGLONG ADT_DURATION_ONE_DAY = (LONGLONG)(24 * 3600 * 10000000i64); // no of 100ns intervals per day
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Data types used within this module //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Variables global within this module //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Services exported by this module. //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildUlongString(
|
|
IN ULONG Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed value.
|
|
|
|
The resultant string will be formatted as a decimal value with not
|
|
more than 10 digits.
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
//
|
|
// Maximum length is 10 wchar characters plus a null termination character.
|
|
//
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = 11 * sizeof(WCHAR); // 10 digits & null termination
|
|
|
|
ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
|
|
ResultantString->MaximumLength);
|
|
if (ResultantString->Buffer == NULL) {
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
|
|
Status = RtlIntegerToUnicodeString( Value, 10, ResultantString );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
(*FreeWhenDone) = TRUE;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildHexUlongString(
|
|
IN ULONG Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed value.
|
|
|
|
The resultant string will be formatted as a hexidecimal value with not
|
|
more than 10 digits.
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
//
|
|
// Maximum length is 10 wchar characters plus a null termination character.
|
|
//
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = 11 * sizeof(WCHAR); // 8 digits, a 0x, & null termination
|
|
|
|
ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
|
|
ResultantString->MaximumLength);
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
|
|
ResultantString->Buffer[0] = L'0';
|
|
ResultantString->Buffer[1] = L'x';
|
|
ResultantString->Buffer += 2;
|
|
|
|
Status = RtlIntegerToUnicodeString( Value, 16, ResultantString );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
//
|
|
// Subtract off the two
|
|
//
|
|
|
|
ResultantString->Buffer -= 2;
|
|
ResultantString->Length += 2 * sizeof(WCHAR);
|
|
|
|
(*FreeWhenDone) = TRUE;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildHexInt64String(
|
|
IN PULONGLONG Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed value.
|
|
|
|
The resultant string will be formatted as a hexidecimal value with not
|
|
more than 18 digits.
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
int Length;
|
|
|
|
|
|
//
|
|
// Maximum length is 18 wchar characters plus a null termination character.
|
|
//
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = 19 * sizeof(WCHAR); // '0x' & 16 digits & null termination
|
|
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Length = _snwprintf(ResultantString->Buffer,
|
|
19,
|
|
L"0x%I64X",
|
|
*Value);
|
|
|
|
ASSERT(3 <= Length && Length <= 18);
|
|
|
|
ResultantString->Length = (USHORT)(Length * sizeof(WCHAR));
|
|
|
|
(*FreeWhenDone) = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildPtrString(
|
|
IN PVOID Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed pointer.
|
|
|
|
The resultant string will be formatted as a decimal value.
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
USHORT NumChars;
|
|
PCWSTR szFormat;
|
|
|
|
ResultantString->Length = 0;
|
|
//
|
|
// Maximum length: sign (+ / -) + 20 decimal digits + null + 2 bonus == 24 chars
|
|
//
|
|
ResultantString->MaximumLength = 24 * sizeof(WCHAR);
|
|
|
|
ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
|
|
ResultantString->MaximumLength);
|
|
if (ResultantString->Buffer == NULL) {
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
} else {
|
|
|
|
#if _WIN64
|
|
szFormat = L"%I64d";
|
|
#else
|
|
szFormat = L"%ld";
|
|
#endif
|
|
|
|
NumChars = (USHORT) wsprintf( ResultantString->Buffer, szFormat, Value );
|
|
|
|
ResultantString->Length = NumChars * sizeof(WCHAR);
|
|
|
|
DsysAssertMsg( ResultantString->Length <= ResultantString->MaximumLength,
|
|
"LsapAdtBuildPtrString" );
|
|
|
|
(*FreeWhenDone) = TRUE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildLuidString(
|
|
IN PLUID Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed LUID.
|
|
|
|
The resultant string will be formatted as follows:
|
|
|
|
(0x00005678,0x12340000)
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING IntegerString;
|
|
WCHAR Buffer[16];
|
|
|
|
|
|
IntegerString.Buffer = (PWCHAR)&Buffer[0];
|
|
IntegerString.MaximumLength = sizeof(Buffer);
|
|
|
|
|
|
//
|
|
// Length (in WCHARS) is 3 for (0x
|
|
// 10 for 1st hex number
|
|
// 3 for ,0x
|
|
// 10 for 2nd hex number
|
|
// 1 for )
|
|
// 1 for null termination
|
|
//
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = 28 * sizeof(WCHAR);
|
|
|
|
ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
|
|
ResultantString->MaximumLength);
|
|
if (ResultantString->Buffer == NULL) {
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
|
|
|
|
Status = RtlAppendUnicodeToString( ResultantString, L"(0x" );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
Status = RtlIntegerToUnicodeString( Value->HighPart, 16, &IntegerString );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
Status = RtlAppendUnicodeToString( ResultantString, IntegerString.Buffer );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
Status = RtlAppendUnicodeToString( ResultantString, L",0x" );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
Status = RtlIntegerToUnicodeString( Value->LowPart, 16, &IntegerString );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
Status = RtlAppendUnicodeToString( ResultantString, IntegerString.Buffer );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
Status = RtlAppendUnicodeToString( ResultantString, L")" );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
(*FreeWhenDone) = TRUE;
|
|
return(STATUS_SUCCESS);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildSidString(
|
|
IN PSID Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed LUID.
|
|
|
|
The resultant string will be formatted as follows:
|
|
|
|
S-1-281736-12-72-9-110
|
|
^ ^^ ^^ ^ ^^^
|
|
| | | | |
|
|
+-----+--+-+--+---- Decimal
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status=STATUS_NO_MEMORY;
|
|
LPWSTR UniBuffer=NULL;
|
|
USHORT Len;
|
|
USHORT MaxLen;
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
//
|
|
// Longhorn-ISSUE-2002/03/11-kumarp : replace 256 by the constant that Kedar
|
|
// is going to define
|
|
//
|
|
|
|
//
|
|
// Note: RtlConvertSidToUnicodeString also uses a hard-coded const 256
|
|
// to generate the string SID.
|
|
//
|
|
MaxLen = (256+3) * sizeof(WCHAR);
|
|
UniBuffer = LsapAllocateLsaHeap(MaxLen);
|
|
|
|
if (UniBuffer)
|
|
{
|
|
ResultantString->Buffer = UniBuffer+2;
|
|
ResultantString->MaximumLength = MaxLen;
|
|
Status = RtlConvertSidToUnicodeString( ResultantString, Value, FALSE );
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
*FreeWhenDone = TRUE;
|
|
UniBuffer[0] = L'%';
|
|
UniBuffer[1] = L'{';
|
|
Len = ResultantString->Length / sizeof(WCHAR);
|
|
UniBuffer[Len+2] = L'}';
|
|
UniBuffer[Len+3] = UNICODE_NULL;
|
|
ResultantString->Buffer = UniBuffer;
|
|
ResultantString->Length = (Len+3)*sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
LsapFreeLsaHeap(UniBuffer);
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildDashString(
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns a string containing a dash ("-").
|
|
This is commonly used to represent "No value" in audit records.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_SUCCESS only.
|
|
|
|
--*/
|
|
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
|
|
(*FreeWhenDone) = FALSE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildLogonIdStrings(
|
|
IN PLUID LogonId,
|
|
OUT PUNICODE_STRING ResultantString1,
|
|
OUT PBOOLEAN FreeWhenDone1,
|
|
OUT PUNICODE_STRING ResultantString2,
|
|
OUT PBOOLEAN FreeWhenDone2,
|
|
OUT PUNICODE_STRING ResultantString3,
|
|
OUT PBOOLEAN FreeWhenDone3
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a 3 unicode strings representing the specified
|
|
logon ID. These strings will contain the username, domain, and
|
|
LUID string of the specified logon session (respectively).
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The logon ID.
|
|
|
|
ResultantString1 - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
This parameter will contain the username.
|
|
|
|
|
|
FreeWhenDone1 - If TRUE, indicates that the buffer of ResultantString1
|
|
must be freed to process heap when no longer needed.
|
|
|
|
ResultantString2 - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
This parameter will contain the username.
|
|
|
|
|
|
FreeWhenDone2 - If TRUE, indicates that the buffer of ResultantString2
|
|
must be freed to process heap when no longer needed.
|
|
|
|
ResultantString3 - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
This parameter will contain the username.
|
|
|
|
|
|
FreeWhenDone3 - If TRUE, indicates that the buffer of ResultantString3
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Try to convert the LUID first.
|
|
//
|
|
|
|
Status = LsapAdtBuildLuidString( LogonId, ResultantString3, FreeWhenDone3 );
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
|
|
//
|
|
// Now get the username and domain names
|
|
//
|
|
|
|
Status = LsapGetLogonSessionAccountInfo( LogonId,
|
|
ResultantString1,
|
|
ResultantString2
|
|
);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
(*FreeWhenDone1) = TRUE;
|
|
(*FreeWhenDone2) = TRUE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// The LUID may be the system LUID
|
|
//
|
|
|
|
LUID SystemLuid = SYSTEM_LUID;
|
|
|
|
if ( RtlEqualLuid( LogonId, &SystemLuid )) {
|
|
|
|
RtlInitUnicodeString(ResultantString1, L"SYSTEM");
|
|
RtlInitUnicodeString(ResultantString2, L"SYSTEM");
|
|
|
|
(*FreeWhenDone1) = FALSE;
|
|
(*FreeWhenDone2) = FALSE;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else if ( Status == STATUS_NO_SUCH_LOGON_SESSION ) {
|
|
|
|
//
|
|
// if the logon session went away (due to a logoff)
|
|
// before we could generate this audit, just use '-'
|
|
// for user/domain name. We still have the logon ID
|
|
// which can be used to locate the logon audit to get
|
|
// user/domain info.
|
|
//
|
|
|
|
RtlInitUnicodeString(ResultantString1, L"-");
|
|
RtlInitUnicodeString(ResultantString2, L"-");
|
|
|
|
(*FreeWhenDone1) = FALSE;
|
|
(*FreeWhenDone2) = FALSE;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
//
|
|
// We have no clue what this is, just free what we've
|
|
// allocated.
|
|
//
|
|
|
|
if ((FreeWhenDone3)) {
|
|
LsapFreeLsaHeap( ResultantString3->Buffer );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildTimeString(
|
|
IN PLARGE_INTEGER Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed time.
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
BOOL b = TRUE;
|
|
SYSTEMTIME SystemTime = {0};
|
|
FILETIME LocalFileTime = {0};
|
|
USHORT Length = 0;
|
|
WCHAR DataString[128];
|
|
|
|
|
|
//
|
|
// Check whether the time is valid.
|
|
// A valid time must be > 0.
|
|
//
|
|
|
|
if (Value->QuadPart <= ADT_DURATION_ONE_DAY)
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// First convert time to readable format.
|
|
//
|
|
|
|
b = FileTimeToLocalFileTime(
|
|
(PFILETIME)Value,
|
|
&LocalFileTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
b = FileTimeToSystemTime(
|
|
&LocalFileTime,
|
|
&SystemTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if (0 == GetTimeFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&SystemTime,
|
|
NULL,
|
|
DataString,
|
|
128
|
|
))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Length = (USHORT) wcslen( DataString );
|
|
|
|
ResultantString->MaximumLength = sizeof(WCHAR) * Length;
|
|
ResultantString->Length = sizeof(WCHAR) * Length;
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(sizeof(WCHAR) * Length);
|
|
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
ResultantString->Buffer,
|
|
DataString,
|
|
sizeof(WCHAR) * Length
|
|
);
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildDateString(
|
|
IN PLARGE_INTEGER Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed date.
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
BOOL b = TRUE;
|
|
SYSTEMTIME SystemTime = {0};
|
|
FILETIME LocalFileTime = {0};
|
|
USHORT Length = 0;
|
|
WCHAR DataString[128];
|
|
|
|
|
|
//
|
|
// Check whether the time is valid.
|
|
// A valid time must be > 0.
|
|
//
|
|
|
|
if (Value->QuadPart <= ADT_DURATION_ONE_DAY)
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Convert time to readable format.
|
|
//
|
|
|
|
b = FileTimeToLocalFileTime(
|
|
(PFILETIME)Value,
|
|
&LocalFileTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
b = FileTimeToSystemTime(
|
|
&LocalFileTime,
|
|
&SystemTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if (0 == GetDateFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&SystemTime,
|
|
NULL,
|
|
DataString,
|
|
128
|
|
))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Length = (USHORT) wcslen( DataString );
|
|
|
|
ResultantString->MaximumLength = sizeof(WCHAR) * Length;
|
|
ResultantString->Length = sizeof(WCHAR) * Length;
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(sizeof(WCHAR) * Length);
|
|
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
ResultantString->Buffer,
|
|
DataString,
|
|
sizeof(WCHAR) * Length
|
|
);
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildDateTimeString(
|
|
IN PLARGE_INTEGER Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed
|
|
date and time.
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
BOOL b = TRUE;
|
|
SYSTEMTIME SystemTime = {0};
|
|
FILETIME LocalFileTime = {0};
|
|
USHORT Length = 0;
|
|
USHORT DateLength = 0;
|
|
USHORT TimeLength = 0;
|
|
WCHAR DateString[128];
|
|
WCHAR TimeString[128];
|
|
|
|
|
|
//
|
|
// Check whether the time is valid.
|
|
// A valid time must be > 0.
|
|
//
|
|
|
|
if (Value->QuadPart <= ADT_DURATION_ONE_DAY)
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// First convert time to readable format.
|
|
//
|
|
|
|
b = FileTimeToLocalFileTime(
|
|
(PFILETIME)Value,
|
|
&LocalFileTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
b = FileTimeToSystemTime(
|
|
&LocalFileTime,
|
|
&SystemTime
|
|
);
|
|
|
|
if (!b)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if (0 == GetDateFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&SystemTime,
|
|
NULL,
|
|
DateString,
|
|
128
|
|
))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if (0 == GetTimeFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
&SystemTime,
|
|
NULL,
|
|
TimeString,
|
|
128
|
|
))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
DateLength = (USHORT) wcslen(DateString);
|
|
TimeLength = (USHORT) wcslen(TimeString);
|
|
|
|
Length = DateLength;
|
|
Length += 1; // for the blank
|
|
Length += TimeLength;
|
|
|
|
ResultantString->MaximumLength = sizeof(WCHAR) * Length;
|
|
ResultantString->Length = sizeof(WCHAR) * Length;
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(
|
|
ResultantString->MaximumLength);
|
|
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
RtlCopyMemory(
|
|
ResultantString->Buffer,
|
|
DateString,
|
|
sizeof(WCHAR) * DateLength
|
|
);
|
|
|
|
RtlCopyMemory(
|
|
ResultantString->Buffer + DateLength,
|
|
L" ",
|
|
sizeof(WCHAR) * 1
|
|
);
|
|
|
|
RtlCopyMemory(
|
|
ResultantString->Buffer + DateLength + 1,
|
|
TimeString,
|
|
sizeof(WCHAR) * TimeLength
|
|
);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildDurationString(
|
|
IN PLARGE_INTEGER Value,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed
|
|
duration in seconds.
|
|
|
|
|
|
Arguments:
|
|
|
|
Value - The value to be transformed to printable format (Unicode string).
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
All other Result Codes are generated by called routines.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LONGLONG Seconds = Value->QuadPart;
|
|
ULONG Length = 0;
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
|
|
//
|
|
// Check whether we got a negative value.
|
|
// In the kernel, durations are expressed as negative numbers.
|
|
//
|
|
|
|
if (Seconds < 0)
|
|
{
|
|
Seconds *= -1;
|
|
}
|
|
|
|
|
|
//
|
|
// Display the duration as a number of seconds.
|
|
//
|
|
|
|
Seconds /= ADT_DURATION_ONE_SEC; // get from 100ns intervals to seconds.
|
|
|
|
|
|
//
|
|
// Maximum length is 13 wchar characters plus a null termination character.
|
|
//
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = 16 * sizeof(WCHAR);
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (ResultantString->Buffer == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
Length = _snwprintf(ResultantString->Buffer,
|
|
16,
|
|
L"%I64u",
|
|
Seconds);
|
|
|
|
ASSERT(1 <= Length && Length <= 15);
|
|
|
|
ResultantString->Length = (USHORT)(Length * sizeof(WCHAR));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildGuidString(
|
|
IN LPGUID pGuid,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed GUID.
|
|
|
|
Arguments:
|
|
|
|
pGuid - The GUID to be transformed to printable format.
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
The string will be in this format:
|
|
"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// num chars required to hold {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
//
|
|
|
|
#define NUM_GUID_STRING_CHARS 38
|
|
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
|
|
ResultantString->Length = NUM_GUID_STRING_CHARS*sizeof(WCHAR);
|
|
ResultantString->MaximumLength = (NUM_GUID_STRING_CHARS+1)*sizeof(WCHAR);
|
|
|
|
ResultantString->Buffer =
|
|
LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (!ResultantString->Buffer)
|
|
{
|
|
*FreeWhenDone = FALSE;
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
Status = STATUS_SUCCESS;
|
|
|
|
#if DBG
|
|
{
|
|
ULONG NumChars;
|
|
NumChars =
|
|
#endif
|
|
swprintf(ResultantString->Buffer,
|
|
L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
|
pGuid->Data1,
|
|
pGuid->Data2,
|
|
pGuid->Data3,
|
|
pGuid->Data4[0],
|
|
pGuid->Data4[1],
|
|
pGuid->Data4[2],
|
|
pGuid->Data4[3],
|
|
pGuid->Data4[4],
|
|
pGuid->Data4[5],
|
|
pGuid->Data4[6],
|
|
pGuid->Data4[7]);
|
|
#if DBG
|
|
ASSERT( NumChars == NUM_GUID_STRING_CHARS );
|
|
}
|
|
#endif
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildStringListString(
|
|
IN PLSA_ADT_STRING_LIST pList,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the strings
|
|
in the passed string list.
|
|
|
|
|
|
Arguments:
|
|
|
|
pList - The StringList to be transformed to printable format.
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
Other status values can be returned from called functions.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = sizeof(WCHAR); // terminating \0
|
|
ULONG i;
|
|
PLSA_ADT_STRING_LIST_ENTRY pEntry;
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
|
|
//
|
|
// Output a dash if the list is empty.
|
|
//
|
|
|
|
if (pList == 0 || pList->cStrings == 0)
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Figure out how long the string is going to be.
|
|
// Each sid will be displayed as '\n\r\t\tstring'.
|
|
// Thus, we will need 4 + length of string wchars per entry.
|
|
//
|
|
|
|
for (
|
|
i = 0, pEntry = pList->Strings;
|
|
i < pList->cStrings;
|
|
i++, pEntry++)
|
|
{
|
|
Length += 4 * sizeof(WCHAR);
|
|
Length += pEntry->String.Length;
|
|
}
|
|
|
|
if (Length > 0xFFFF)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = (USHORT)Length;
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (ResultantString->Buffer == 0)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
|
|
//
|
|
// Build the resultant string.
|
|
//
|
|
|
|
for (
|
|
i = 0, pEntry = pList->Strings;
|
|
i < pList->cStrings;
|
|
i++, pEntry++)
|
|
{
|
|
Status = RtlAppendUnicodeToString(ResultantString, L"\r\n\t\t");
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
Status = RtlAppendUnicodeStringToString(ResultantString, &pEntry->String);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildSidListString(
|
|
IN PLSA_ADT_SID_LIST pList,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the sids
|
|
in the passed sid list.
|
|
|
|
|
|
Arguments:
|
|
|
|
pList - The SidList to be transformed to printable format.
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
|
|
Other status values can be returned from called functions.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = sizeof(WCHAR); // terminating \0
|
|
//ULONG SidLength;
|
|
WCHAR SidStringBuffer[256];
|
|
UNICODE_STRING SidString;
|
|
ULONG i;
|
|
PLSA_ADT_SID_LIST_ENTRY pEntry;
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
|
|
//
|
|
// Output a dash if the list is empty.
|
|
//
|
|
|
|
if (pList == 0 || pList->cSids == 0)
|
|
{
|
|
RtlInitUnicodeString(ResultantString, L"-");
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Figure out how long the string is going to be.
|
|
// Each sid will be displayed as '\n\r\t\t%{sid_as_string}'.
|
|
// Thus, we will need 7 + length of sid_as_string wchars per sid.
|
|
//
|
|
// Using the 'official' length for a stringized sid - 256 chars from
|
|
// the above LsapAdtBuildSidString function.
|
|
// Once we can link RtlLengthSidAsUnicodeString again we can use it
|
|
// and not waste so much memory (see below fragment).
|
|
//
|
|
|
|
Length = ((7 + 256) * pList->cSids + 1) * sizeof(WCHAR);
|
|
|
|
/*
|
|
for (
|
|
i = 0, pEntry = pList->Sids;
|
|
i < pList->cSids;
|
|
i++, pEntry++)
|
|
{
|
|
Status = RtlLengthSidAsUnicodeString(
|
|
pEntry->Sid,
|
|
&SidLength);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Length += 7 * sizeof(WCHAR);
|
|
Length += SidLength;
|
|
}
|
|
*/
|
|
if (Length > 0xFFFF)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = (USHORT)Length;
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (ResultantString->Buffer == 0)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
SidString.Length = 0;
|
|
SidString.MaximumLength = sizeof(SidStringBuffer);
|
|
SidString.Buffer = SidStringBuffer;
|
|
|
|
|
|
//
|
|
// Build the resultant string.
|
|
//
|
|
|
|
for (
|
|
i = 0, pEntry = pList->Sids;
|
|
i < pList->cSids;
|
|
i++, pEntry++)
|
|
{
|
|
Status = RtlConvertSidToUnicodeString(&SidString, pEntry->Sid, FALSE);
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = RtlAppendUnicodeToString(ResultantString, L"\r\n\t\t%{");
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
Status = RtlAppendUnicodeStringToString(ResultantString, &SidString);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
Status = RtlAppendUnicodeToString(ResultantString, L"}");
|
|
ASSERT(NT_SUCCESS(Status));
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildMessageString(
|
|
IN ULONG MessageId,
|
|
OUT PUNICODE_STRING ResultantString,
|
|
OUT PBOOLEAN FreeWhenDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string saying that 'the bitmap
|
|
value has changed, but we are not displaying it'. Currently it is
|
|
only used to support tha SAM LogonHours extended attribute.
|
|
|
|
Arguments:
|
|
|
|
ResultantString - Points to the unicode string header. The body of this
|
|
unicode string will be set to point to the resultant output value
|
|
if successful. Otherwise, the Buffer field of this parameter
|
|
will be set to NULL.
|
|
The string will be of this format:
|
|
"%%nnnnnnnnnn"
|
|
|
|
FreeWhenDone - If TRUE, indicates that the buffer of the ResultantString
|
|
must be freed to process heap when no longer needed.
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
for the string body.
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Length;
|
|
const ULONG NumChars = 12; // %%nnnnnnnnnn
|
|
|
|
*FreeWhenDone = FALSE;
|
|
|
|
ResultantString->Length = 0;
|
|
ResultantString->MaximumLength = (USHORT)((NumChars + 1) * sizeof(WCHAR));
|
|
ResultantString->Buffer = LsapAllocateLsaHeap(ResultantString->MaximumLength);
|
|
|
|
if (!ResultantString->Buffer)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone = TRUE;
|
|
|
|
Length = _snwprintf(
|
|
ResultantString->Buffer,
|
|
NumChars + 1,
|
|
L"%%%%%u",
|
|
MessageId);
|
|
|
|
ASSERT(1 <= Length && Length <= NumChars);
|
|
|
|
ResultantString->Length = (USHORT)(Length * sizeof(WCHAR));
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildIPv4Strings(
|
|
IN SOCKADDR_IN* pSockAddr,
|
|
OUT PUNICODE_STRING ResultantString1,
|
|
OUT PBOOLEAN FreeWhenDone1,
|
|
OUT PUNICODE_STRING ResultantString2,
|
|
OUT PBOOLEAN FreeWhenDone2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds unicode strings representing the passed SOCKADDR_IN
|
|
structure.
|
|
|
|
Arguments:
|
|
pSockAddr - address to be converted to string format
|
|
|
|
ResultantString1 - receives the IPv4 address
|
|
|
|
FreeWhenDone1 - set to TRUE if the caller should free ResultantString1
|
|
|
|
ResultantString2 - receives the port number
|
|
|
|
FreeWhenDone2 - set to TRUE if the caller should free ResultantString2
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
|
|
STATUS_SUCCESS - on success
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
WORD PortNumber = 0;
|
|
|
|
|
|
//
|
|
// the limits are in number of characters
|
|
//
|
|
const USHORT MAX_IP4_ADDR_LEN = 16;
|
|
CONST USHORT MAX_IP4_PORT_LEN = 8;
|
|
|
|
DWORD dwAddressType;
|
|
|
|
|
|
*FreeWhenDone1 = FALSE;
|
|
*FreeWhenDone2 = FALSE;
|
|
|
|
dwAddressType = pSockAddr->sin_family;
|
|
|
|
//
|
|
// we only handle IPv4 address. check what we have got
|
|
//
|
|
|
|
if (dwAddressType != AF_INET)
|
|
{
|
|
Status = STATUS_INVALID_ADDRESS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// format the IP address
|
|
//
|
|
|
|
ResultantString1->MaximumLength = MAX_IP4_ADDR_LEN * sizeof(WCHAR);
|
|
ResultantString1->Buffer = LsapAllocateLsaHeap(ResultantString1->MaximumLength);
|
|
|
|
if ( !ResultantString1->Buffer )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone1 = TRUE;
|
|
|
|
ResultantString1->Length =
|
|
(USHORT) swprintf(ResultantString1->Buffer, L"%d.%d.%d.%d",
|
|
pSockAddr->sin_addr.S_un.S_un_b.s_b1,
|
|
pSockAddr->sin_addr.S_un.S_un_b.s_b2,
|
|
pSockAddr->sin_addr.S_un.S_un_b.s_b3,
|
|
pSockAddr->sin_addr.S_un.S_un_b.s_b4
|
|
) * sizeof(WCHAR);
|
|
|
|
//
|
|
// format the port number
|
|
//
|
|
|
|
ResultantString2->MaximumLength = MAX_IP4_PORT_LEN * sizeof(WCHAR);
|
|
ResultantString2->Buffer = LsapAllocateLsaHeap(ResultantString2->MaximumLength);
|
|
|
|
if ( !ResultantString2->Buffer )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone2 = TRUE;
|
|
|
|
PortNumber = pSockAddr->sin_port;
|
|
|
|
//
|
|
// The port address is in network order which is big-endian.
|
|
// Convert it to little-endian if we are running on a little-endian machine.
|
|
//
|
|
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
PortNumber = ((PortNumber & 0xff) << 8) | ((PortNumber & 0xff00) >> 8);
|
|
#endif
|
|
|
|
ResultantString2->Length =
|
|
(USHORT) swprintf(ResultantString2->Buffer, L"%d", PortNumber)
|
|
* sizeof(WCHAR);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (*FreeWhenDone1)
|
|
{
|
|
*FreeWhenDone1 = FALSE;
|
|
LsapFreeLsaHeap( ResultantString1->Buffer );
|
|
}
|
|
|
|
if (*FreeWhenDone2)
|
|
{
|
|
*FreeWhenDone2 = FALSE;
|
|
LsapFreeLsaHeap( ResultantString2->Buffer );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildIPv6Strings(
|
|
IN SOCKADDR_IN6* pSockAddr,
|
|
OUT PUNICODE_STRING ResultantString1,
|
|
OUT PBOOLEAN FreeWhenDone1,
|
|
OUT PUNICODE_STRING ResultantString2,
|
|
OUT PBOOLEAN FreeWhenDone2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds unicode strings representing the passed SOCKADDR_IN6
|
|
structure.
|
|
|
|
Arguments:
|
|
pSockAddr - address to be converted to string format
|
|
|
|
ResultantString1 - receives the IPv6 address
|
|
|
|
FreeWhenDone1 - set to TRUE if the caller should free ResultantString1
|
|
|
|
ResultantString2 - receives the port number
|
|
|
|
FreeWhenDone2 - set to TRUE if the caller should free ResultantString2
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
|
|
STATUS_SUCCESS - on success
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
|
|
//
|
|
// IPv6 address is in the following formats:
|
|
//
|
|
// hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh OR
|
|
// hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:ddd.ddd.ddd.ddd
|
|
//
|
|
// where
|
|
// - hhhh is 1 to 4 digit hex number
|
|
// - ddd is 1 to 3 digit decimal number
|
|
//
|
|
// the limits below are in number of characters
|
|
//
|
|
const USHORT MAX_IP6_ADDR_LEN = (4*8 + 7 + 3*4 + 3 + 1);
|
|
const USHORT MAX_IP6_PORT_LEN = 8;
|
|
|
|
DWORD dwAddressType;
|
|
|
|
|
|
*FreeWhenDone1 = FALSE;
|
|
*FreeWhenDone2 = FALSE;
|
|
|
|
dwAddressType = pSockAddr->sin6_family;
|
|
|
|
//
|
|
// we only handle IPv6 address. check what we have got
|
|
//
|
|
|
|
if (dwAddressType != AF_INET6)
|
|
{
|
|
Status = STATUS_INVALID_ADDRESS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// format the IP address
|
|
//
|
|
|
|
ResultantString1->MaximumLength = MAX_IP6_ADDR_LEN * sizeof(WCHAR);
|
|
ResultantString1->Buffer = LsapAllocateLsaHeap(ResultantString1->MaximumLength);
|
|
|
|
if ( !ResultantString1->Buffer )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone1 = TRUE;
|
|
|
|
ResultantString1->Length =
|
|
(USHORT) MyIp6AddressToString(
|
|
&pSockAddr->sin6_addr,
|
|
ResultantString1->Buffer,
|
|
ResultantString1->MaximumLength / sizeof(WCHAR)
|
|
) * sizeof(WCHAR);
|
|
//
|
|
// format the port number
|
|
//
|
|
|
|
ResultantString2->MaximumLength = MAX_IP6_PORT_LEN * sizeof(WCHAR);
|
|
ResultantString2->Buffer = LsapAllocateLsaHeap(ResultantString2->MaximumLength);
|
|
|
|
if ( !ResultantString2->Buffer )
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*FreeWhenDone2 = TRUE;
|
|
|
|
ResultantString2->Length =
|
|
(USHORT) swprintf(ResultantString2->Buffer, L"%d",
|
|
pSockAddr->sin6_port) * sizeof(WCHAR);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (*FreeWhenDone1)
|
|
{
|
|
*FreeWhenDone1 = FALSE;
|
|
LsapFreeLsaHeap( ResultantString1->Buffer );
|
|
}
|
|
|
|
if (*FreeWhenDone2)
|
|
{
|
|
*FreeWhenDone2 = FALSE;
|
|
LsapFreeLsaHeap( ResultantString2->Buffer );
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtBuildSockAddrString(
|
|
IN PSOCKADDR pSockAddr,
|
|
OUT PUNICODE_STRING ResultantString1,
|
|
OUT PBOOLEAN FreeWhenDone1,
|
|
OUT PUNICODE_STRING ResultantString2,
|
|
OUT PBOOLEAN FreeWhenDone2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function builds a unicode string representing the passed
|
|
SOCKADDR_IN/SOCKADDR_IN6 structure. The sin_family member is inspected
|
|
to determine if the passed in pointer is SOCKADDR_IN or SOCKADDR_IN6 type.
|
|
|
|
|
|
Arguments:
|
|
pSockAddr - address to be converted to string format
|
|
|
|
ResultantString1 - receives the IP address
|
|
|
|
FreeWhenDone1 - set to TRUE if the caller should free ResultantString1
|
|
|
|
ResultantString2 - receives the port number
|
|
|
|
FreeWhenDone2 - set to TRUE if the caller should free ResultantString2
|
|
|
|
|
|
Return Values:
|
|
|
|
STATUS_NO_MEMORY - indicates memory could not be allocated
|
|
|
|
STATUS_SUCCESS - on success
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
DWORD dwAddressType;
|
|
|
|
|
|
*FreeWhenDone1 = FALSE;
|
|
*FreeWhenDone2 = FALSE;
|
|
|
|
dwAddressType = pSockAddr->sa_family;
|
|
|
|
//
|
|
// we only handle IPv4 and IPv6 addresses. check what we have got
|
|
//
|
|
|
|
if (dwAddressType == AF_INET)
|
|
{
|
|
Status = LsapAdtBuildIPv4Strings(
|
|
(SOCKADDR_IN*) pSockAddr,
|
|
ResultantString1,
|
|
FreeWhenDone1,
|
|
ResultantString2,
|
|
FreeWhenDone2
|
|
);
|
|
}
|
|
else if (dwAddressType == AF_INET6)
|
|
{
|
|
Status = LsapAdtBuildIPv6Strings(
|
|
(SOCKADDR_IN6*) pSockAddr,
|
|
ResultantString1,
|
|
FreeWhenDone1,
|
|
ResultantString2,
|
|
FreeWhenDone2
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// either unknown address type or the address is not provided,
|
|
// just use '-' for address/port
|
|
//
|
|
|
|
(VOID) LsapAdtBuildDashString( ResultantString1, FreeWhenDone1 );
|
|
(VOID) LsapAdtBuildDashString( ResultantString2, FreeWhenDone2 );
|
|
|
|
Status = STATUS_SUCCESS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|