Leaked source code of windows server 2003
 
 
 
 
 
 

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;
}