mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1175 lines
23 KiB
1175 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
util.cxx
|
|
|
|
Abstract:
|
|
|
|
Utility routines
|
|
|
|
Author:
|
|
|
|
Cliff Van Dyke (cliffv) 11-Apr-2001
|
|
|
|
--*/
|
|
|
|
|
|
#include "pch.hxx"
|
|
|
|
#if DBG
|
|
//
|
|
// List of all allocated blocks
|
|
// AccessSerialized by AzGlAllocatorCritSect
|
|
LIST_ENTRY AzGlAllocatedBlocks;
|
|
CRITICAL_SECTION AzGlAllocatorCritSect;
|
|
|
|
#endif // DBG
|
|
|
|
|
|
|
|
PVOID
|
|
AzpAllocateHeap(
|
|
IN SIZE_T Size
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Memory allocator
|
|
|
|
Arguments
|
|
|
|
Size - Size (in bytes) to allocate
|
|
|
|
Return Value
|
|
|
|
Returns a pointer to the allocated memory.
|
|
NULL - Not enough memory
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
ULONG HeaderSize = ROUND_UP_COUNT( sizeof(LIST_ENTRY), ALIGN_WORST );
|
|
|
|
PLIST_ENTRY RealBlock;
|
|
|
|
//
|
|
// Allocate a block with a header
|
|
//
|
|
|
|
RealBlock = (PLIST_ENTRY) LocalAlloc( 0, HeaderSize + Size );
|
|
|
|
if ( RealBlock == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Link the block since we're nosey.
|
|
//
|
|
|
|
EnterCriticalSection( &AzGlAllocatorCritSect );
|
|
InsertHeadList( &AzGlAllocatedBlocks, RealBlock );
|
|
LeaveCriticalSection( &AzGlAllocatorCritSect );
|
|
|
|
return (PVOID)(((LPBYTE)RealBlock)+HeaderSize);
|
|
|
|
#else // DBG
|
|
return LocalAlloc( 0, Size );
|
|
#endif // DBG
|
|
}
|
|
|
|
VOID
|
|
AzpFreeHeap(
|
|
IN PVOID Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Memory de-allocator
|
|
|
|
Arguments
|
|
|
|
Buffer - address of buffer to free
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
#if DBG
|
|
ULONG HeaderSize = ROUND_UP_COUNT( sizeof(LIST_ENTRY), ALIGN_WORST );
|
|
PLIST_ENTRY RealBlock;
|
|
|
|
RealBlock = (PLIST_ENTRY)(((LPBYTE)Buffer)-HeaderSize);
|
|
|
|
EnterCriticalSection( &AzGlAllocatorCritSect );
|
|
RemoveEntryList( RealBlock );
|
|
LeaveCriticalSection( &AzGlAllocatorCritSect );
|
|
|
|
LocalFree( RealBlock );
|
|
#else // DBG
|
|
LocalFree( Buffer );
|
|
#endif // DBG
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AzpInitString(
|
|
OUT PAZP_STRING AzpString,
|
|
IN LPWSTR String OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Initialize our private string structure to point to a passed in string.
|
|
|
|
Arguments
|
|
|
|
AzpString - Initialized string
|
|
|
|
String - zero terminated string to be reference
|
|
If NULL, AzpString will be initialized to empty.
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
if ( String == NULL ) {
|
|
AzpString->String = NULL;
|
|
AzpString->StringSize = 0;
|
|
} else {
|
|
AzpString->String = String;
|
|
AzpString->StringSize = (ULONG) ((wcslen(String)+1)*sizeof(WCHAR));
|
|
}
|
|
|
|
}
|
|
|
|
DWORD
|
|
AzpCaptureString(
|
|
OUT PAZP_STRING AzpString,
|
|
IN LPCWSTR String,
|
|
IN ULONG MaximumLength,
|
|
IN BOOLEAN NullOk
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Capture the passed in string.
|
|
|
|
Arguments
|
|
|
|
AzpString - Captured copy of the passed in string.
|
|
On success, string must be freed using AzpFreeString
|
|
|
|
String - zero terminated string to capture
|
|
|
|
MaximumLength - Maximum length of the string (in characters).
|
|
|
|
NullOk - if TRUE, a NULL string or zero length string is OK.
|
|
|
|
Return Value
|
|
|
|
NO_ERROR - The operation was successful
|
|
ERROR_NOT_ENOUGH_MEMORY - not enough memory
|
|
Other exception status codes
|
|
|
|
--*/
|
|
{
|
|
ULONG WinStatus;
|
|
ULONG StringSize;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
AzpInitString( AzpString, NULL );
|
|
|
|
if ( String == NULL ) {
|
|
if ( !NullOk ) {
|
|
AzPrint(( AZD_INVPARM, "AzpCaptureString: NULL not ok\n" ));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
__try {
|
|
|
|
//
|
|
// Validate a passed in LPWSTR
|
|
//
|
|
|
|
ULONG StringLength;
|
|
|
|
StringLength = (ULONG) wcslen( String );
|
|
|
|
if ( StringLength == 0 ) {
|
|
if ( !NullOk ) {
|
|
AzPrint(( AZD_INVPARM, "AzpCaptureString: zero length not ok\n" ));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if ( StringLength > MaximumLength ) {
|
|
AzPrint(( AZD_INVPARM, "AzpCaptureString: string too long %ld %ld %ws\n", StringLength, MaximumLength, String ));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
StringSize = (StringLength+1)*sizeof(WCHAR);
|
|
|
|
|
|
//
|
|
// Allocate and copy the string
|
|
//
|
|
|
|
AzpString->String = (LPWSTR) AzpAllocateHeap( StringSize );
|
|
|
|
if ( AzpString->String == NULL ) {
|
|
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
|
|
RtlCopyMemory( AzpString->String,
|
|
String,
|
|
StringSize );
|
|
|
|
AzpString->StringSize = StringSize;
|
|
|
|
WinStatus = NO_ERROR;
|
|
}
|
|
|
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
|
|
WinStatus = RtlNtStatusToDosError( GetExceptionCode());
|
|
|
|
AzpFreeString( AzpString );
|
|
}
|
|
|
|
return WinStatus;
|
|
}
|
|
|
|
DWORD
|
|
AzpCaptureSid(
|
|
OUT PAZP_STRING AzpString,
|
|
IN PSID Sid
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Capture the passed in SID
|
|
|
|
Arguments
|
|
|
|
AzpString - Captured copy of the passed in sid.
|
|
On success, string must be freed using AzpFreeString
|
|
|
|
Sid - Sid to capture
|
|
|
|
Return Value
|
|
|
|
NO_ERROR - The operation was successful
|
|
ERROR_NOT_ENOUGH_MEMORY - not enough memory
|
|
Other exception status codes
|
|
|
|
--*/
|
|
{
|
|
ULONG WinStatus;
|
|
ULONG StringSize;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
AzpInitString( AzpString, NULL );
|
|
|
|
|
|
__try {
|
|
|
|
//
|
|
// Validate a passed in SID
|
|
//
|
|
|
|
if ( !RtlValidSid( Sid ) ) {
|
|
AzPrint(( AZD_INVPARM, "AzpCaptureString: SID not valid\n" ));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
StringSize = RtlLengthSid( Sid );
|
|
|
|
//
|
|
// Allocate and copy the SID
|
|
//
|
|
|
|
AzpString->String = (LPWSTR) AzpAllocateHeap( StringSize );
|
|
|
|
if ( AzpString->String == NULL ) {
|
|
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
|
|
RtlCopyMemory( AzpString->String,
|
|
Sid,
|
|
StringSize );
|
|
|
|
AzpString->StringSize = StringSize;
|
|
|
|
WinStatus = NO_ERROR;
|
|
}
|
|
|
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
|
|
WinStatus = RtlNtStatusToDosError( GetExceptionCode());
|
|
|
|
AzpFreeString( AzpString );
|
|
}
|
|
|
|
return WinStatus;
|
|
}
|
|
|
|
DWORD
|
|
AzpCaptureUlong(
|
|
IN PVOID PropertyValue,
|
|
OUT PULONG UlongValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Support routine for the SetProperty API.
|
|
Capture a parameter for the user application.
|
|
|
|
Arguments
|
|
|
|
PropertyValue - Specifies a pointer to the property.
|
|
|
|
UlongValue - Value to return to make a copy of.
|
|
|
|
Return Value
|
|
NO_ERROR - The operation was successful
|
|
Other exception status codes
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD WinStatus;
|
|
|
|
__try {
|
|
*UlongValue = *(PULONG)PropertyValue;
|
|
WinStatus = NO_ERROR;
|
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
WinStatus = RtlNtStatusToDosError( GetExceptionCode());
|
|
}
|
|
|
|
return WinStatus;
|
|
}
|
|
|
|
DWORD
|
|
AzpDuplicateString(
|
|
OUT PAZP_STRING AzpOutString,
|
|
IN PAZP_STRING AzpInString
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Make a duplicate of the passed in string
|
|
|
|
Arguments
|
|
|
|
AzpOutString - Returns a copy of the passed in string.
|
|
On success, string must be freed using AzpFreeString.
|
|
|
|
AzpInString - Specifies a string to make a copy of.
|
|
|
|
Return Value
|
|
|
|
NO_ERROR - The operation was successful
|
|
ERROR_NOT_ENOUGH_MEMORY - not enough memory
|
|
|
|
--*/
|
|
{
|
|
ULONG WinStatus;
|
|
|
|
//
|
|
// Initialization
|
|
//
|
|
|
|
AzpInitString( AzpOutString, NULL );
|
|
|
|
//
|
|
// Handle an empty string
|
|
//
|
|
|
|
if ( AzpInString->StringSize == 0 || AzpInString->String == NULL ) {
|
|
|
|
WinStatus = NO_ERROR;
|
|
|
|
//
|
|
// Allocate and copy the string
|
|
//
|
|
|
|
} else {
|
|
AzpOutString->String = (LPWSTR) AzpAllocateHeap( AzpInString->StringSize );
|
|
|
|
if ( AzpOutString->String == NULL ) {
|
|
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
|
|
RtlCopyMemory( AzpOutString->String,
|
|
AzpInString->String,
|
|
AzpInString->StringSize );
|
|
|
|
AzpOutString->StringSize = AzpInString->StringSize;
|
|
|
|
WinStatus = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return WinStatus;
|
|
}
|
|
|
|
BOOL
|
|
AzpEqualStrings(
|
|
IN PAZP_STRING AzpString1,
|
|
IN PAZP_STRING AzpString2
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Does a case insensitive comparison of two strings
|
|
|
|
Arguments
|
|
|
|
AzpString1 - First string to compare
|
|
|
|
AzpString2 - Second string to compare
|
|
|
|
Return Value
|
|
|
|
TRUE: the strings are equal
|
|
FALSE: the strings are not equal
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Simply compare the strings
|
|
//
|
|
return (AzpCompareStrings( AzpString1, AzpString2 ) == CSTR_EQUAL);
|
|
|
|
}
|
|
|
|
|
|
LONG
|
|
AzpCompareStrings(
|
|
IN PAZP_STRING AzpString1,
|
|
IN PAZP_STRING AzpString2
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Does a case insensitive comparison of two strings
|
|
|
|
Arguments
|
|
|
|
AzpString1 - First string to compare
|
|
|
|
AzpString2 - Second string to compare
|
|
|
|
Return Value
|
|
|
|
0: An error ocurred. Call GetLastError();
|
|
CSTR_LESS_THAN: String 1 is less than string 2
|
|
CSTR_EQUAL: String 1 is equal to string 2
|
|
CSTR_GREATER_THAN: String 1 is greater than string 2
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Handle NULL
|
|
//
|
|
|
|
if ( AzpString1->String == NULL ) {
|
|
if ( AzpString2->String == NULL ) {
|
|
return CSTR_EQUAL;
|
|
}else {
|
|
return CSTR_LESS_THAN;
|
|
}
|
|
} else {
|
|
if ( AzpString2->String == NULL ) {
|
|
return CSTR_GREATER_THAN;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Compare the Unicode strings
|
|
// Don't compare the trailing zero character.
|
|
// (Some callers pass in strings where the trailing character isn't a zero.)
|
|
//
|
|
|
|
return CompareStringW( LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
AzpString1->String,
|
|
(AzpString1->StringSize/sizeof(WCHAR))-1,
|
|
AzpString2->String,
|
|
(AzpString2->StringSize/sizeof(WCHAR))-1 );
|
|
|
|
}
|
|
|
|
VOID
|
|
AzpSwapStrings(
|
|
IN OUT PAZP_STRING AzpString1,
|
|
IN OUT PAZP_STRING AzpString2
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Swap two strings
|
|
|
|
Arguments
|
|
|
|
AzpString1 - First string to swap
|
|
|
|
AzpString2 - Second string to swap
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
AZP_STRING TempString;
|
|
|
|
TempString = *AzpString1;
|
|
*AzpString1 = *AzpString2;
|
|
*AzpString2 = TempString;
|
|
|
|
}
|
|
|
|
VOID
|
|
AzpFreeString(
|
|
IN PAZP_STRING AzpString
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Free the specified string
|
|
|
|
Arguments
|
|
|
|
AzpString - String to be freed.
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if ( AzpString->String != NULL ) {
|
|
AzpFreeHeap( AzpString->String );
|
|
}
|
|
|
|
AzpInitString( AzpString, NULL );
|
|
}
|
|
|
|
|
|
DWORD
|
|
AzpAddPtr(
|
|
IN PAZP_PTR_ARRAY AzpPtrArray,
|
|
IN PVOID Pointer,
|
|
IN ULONG Index
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Inserts a pointer into the array of pointers.
|
|
|
|
The array will be automatically expanded to be large enough to contain the new pointer.
|
|
All existing pointers from slot # 'Index' through the end of the existing array will
|
|
be shifted to later slots.
|
|
|
|
Arguments
|
|
|
|
AzpPtrArray - Array that the pointer will be inserted into.
|
|
|
|
Pointer - Pointer to be inserted.
|
|
|
|
Index - Index into the array where the 'Pointer' will be inserted
|
|
If Index is larger than the current size of the array or AZP_ADD_ENDOFLIST,
|
|
'Pointer' will be inserted after the existing elements of the array.
|
|
|
|
Return Value
|
|
|
|
NO_ERROR - The operation was successful
|
|
ERROR_NOT_ENOUGH_MEMORY - not enough memory
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Ensure Index isn't too large
|
|
//
|
|
|
|
if ( Index > AzpPtrArray->UsedCount ) {
|
|
Index = AzpPtrArray->UsedCount;
|
|
}
|
|
|
|
//
|
|
// If the array isn't large enough, make it bigger
|
|
//
|
|
|
|
if ( AzpPtrArray->UsedCount >= AzpPtrArray->AllocatedCount ) {
|
|
PVOID *TempArray;
|
|
|
|
//
|
|
// Allocate a new array
|
|
//
|
|
|
|
TempArray = (PVOID *) AzpAllocateHeap(
|
|
(AzpPtrArray->AllocatedCount + AZP_PTR_ARRAY_INCREMENT) * sizeof(PVOID) );
|
|
|
|
if ( TempArray == NULL ) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Copy the data into the new array and free the old array
|
|
//
|
|
|
|
if ( AzpPtrArray->Array != NULL ) {
|
|
|
|
RtlCopyMemory( TempArray,
|
|
AzpPtrArray->Array,
|
|
AzpPtrArray->AllocatedCount * sizeof(PVOID) );
|
|
|
|
AzpFreeHeap( AzpPtrArray->Array );
|
|
AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Free old array\n", AzpPtrArray, AzpPtrArray->Array ));
|
|
}
|
|
|
|
//
|
|
// Grab the pointer to the new array and clear the new part of the array
|
|
//
|
|
|
|
AzpPtrArray->Array = TempArray;
|
|
AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Allocate array\n", AzpPtrArray, AzpPtrArray->Array ));
|
|
|
|
RtlZeroMemory( &TempArray[AzpPtrArray->UsedCount],
|
|
AZP_PTR_ARRAY_INCREMENT * sizeof(PVOID) );
|
|
|
|
AzpPtrArray->AllocatedCount += AZP_PTR_ARRAY_INCREMENT;
|
|
|
|
}
|
|
|
|
//
|
|
// Shift any old data
|
|
//
|
|
|
|
if ( Index != AzpPtrArray->UsedCount ) {
|
|
|
|
RtlMoveMemory( &(AzpPtrArray->Array[Index+1]),
|
|
&(AzpPtrArray->Array[Index]),
|
|
(AzpPtrArray->UsedCount-Index) * sizeof(PVOID) );
|
|
}
|
|
|
|
//
|
|
// Insert the new element
|
|
//
|
|
|
|
AzpPtrArray->Array[Index] = Pointer;
|
|
AzpPtrArray->UsedCount ++;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
VOID
|
|
AzpRemovePtrByIndex(
|
|
IN PAZP_PTR_ARRAY AzpPtrArray,
|
|
IN ULONG Index
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Remove a pointer from the array of pointers.
|
|
|
|
All existing pointers from slot # 'Index' through the end of the existing array will
|
|
be shifted to earlier slots.
|
|
|
|
Arguments
|
|
|
|
AzpPtrArray - Array that the pointer will be removed into.
|
|
|
|
Index - Index into the array where the 'Pointer' will be removed from.
|
|
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Ensure Index isn't too large
|
|
//
|
|
|
|
ASSERT( Index < AzpPtrArray->UsedCount );
|
|
|
|
|
|
//
|
|
// Shift any old data
|
|
//
|
|
|
|
if ( Index+1 != AzpPtrArray->UsedCount ) {
|
|
|
|
RtlMoveMemory( &(AzpPtrArray->Array[Index]),
|
|
&(AzpPtrArray->Array[Index+1]),
|
|
(AzpPtrArray->UsedCount-Index-1) * sizeof(PVOID) );
|
|
}
|
|
|
|
//
|
|
// Clear the last element
|
|
//
|
|
|
|
AzpPtrArray->UsedCount--;
|
|
AzpPtrArray->Array[AzpPtrArray->UsedCount] = NULL;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AzpRemovePtrByPtr(
|
|
IN PAZP_PTR_ARRAY AzpPtrArray,
|
|
IN PVOID Pointer
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Removed a pointer from the array of pointers.
|
|
|
|
All existing pointers following the specified pointer will
|
|
be shifted to earlier slots.
|
|
|
|
Arguments
|
|
|
|
AzpPtrArray - Array that the pointer will be removed into.
|
|
|
|
Pointer - Pointer to be removed
|
|
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
BOOLEAN FoundIt = FALSE;
|
|
|
|
for ( i=0; i<AzpPtrArray->UsedCount; i++ ) {
|
|
|
|
if ( Pointer == AzpPtrArray->Array[i] ) {
|
|
AzpRemovePtrByIndex( AzpPtrArray, i );
|
|
FoundIt = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT( FoundIt );
|
|
|
|
}
|
|
|
|
|
|
|
|
PVOID
|
|
AzpGetStringProperty(
|
|
IN PAZP_STRING AzpString
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Support routine for the GetProperty API. Convert an AzpString to the form
|
|
supported by GetProperty.
|
|
|
|
Empty string are returned as Zero length string instead of NULL
|
|
|
|
Arguments
|
|
|
|
AzpString - Specifies a string to make a copy of.
|
|
|
|
Return Value
|
|
|
|
Pointer to allocated string.
|
|
String should be freed using AzFreeMemory.
|
|
NULL - Not enough memory was available to allocate the string
|
|
|
|
--*/
|
|
{
|
|
LPWSTR String;
|
|
ULONG AllocatedSize;
|
|
|
|
//
|
|
// Allocate and copy the string
|
|
//
|
|
|
|
AllocatedSize = AzpString->StringSize ? AzpString->StringSize : sizeof(WCHAR);
|
|
String = (LPWSTR) AzpAllocateHeap( AllocatedSize );
|
|
|
|
if ( String != NULL ) {
|
|
|
|
//
|
|
// Convert NULL strings to zero length strings
|
|
//
|
|
|
|
if ( AzpString->StringSize == 0 ) {
|
|
*String = L'\0';
|
|
|
|
} else {
|
|
|
|
RtlCopyMemory( String,
|
|
AzpString->String,
|
|
AzpString->StringSize );
|
|
}
|
|
|
|
}
|
|
|
|
return String;
|
|
}
|
|
|
|
PVOID
|
|
AzpGetUlongProperty(
|
|
IN ULONG UlongValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Support routine for the GetProperty API. Convert a ULONG to the form
|
|
supported by GetProperty.
|
|
|
|
Arguments
|
|
|
|
UlongValue - Value to return to make a copy of.
|
|
|
|
Return Value
|
|
|
|
Pointer to allocated string.
|
|
String should be freed using AzFreeMemory.
|
|
NULL - Not enough memory was available to allocate the string
|
|
|
|
--*/
|
|
{
|
|
PULONG RetValue;
|
|
|
|
//
|
|
// Allocate and copy the string
|
|
//
|
|
|
|
RetValue = (PULONG) AzpAllocateHeap( sizeof(ULONG) );
|
|
|
|
if ( RetValue != NULL ) {
|
|
|
|
*RetValue = UlongValue;
|
|
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
|
|
//
|
|
// Debugging support
|
|
//
|
|
#ifdef AZROLESDBG
|
|
#include <stdio.h>
|
|
CRITICAL_SECTION AzGlLogFileCritSect;
|
|
ULONG AzGlDbFlag;
|
|
// HANDLE AzGlLogFile;
|
|
|
|
#define MAX_PRINTF_LEN 1024 // Arbitrary.
|
|
|
|
VOID
|
|
AzpPrintRoutineV(
|
|
IN DWORD DebugFlag,
|
|
IN LPSTR Format,
|
|
va_list arglist
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Debug routine for azroles
|
|
|
|
Arguments
|
|
|
|
DebugFlag - Flag to indicating the functionality being debugged
|
|
|
|
--- Other printf parameters
|
|
|
|
Return Value
|
|
|
|
--*/
|
|
|
|
{
|
|
static LPSTR AzGlLogFileOutputBuffer = NULL;
|
|
ULONG length;
|
|
int lengthTmp;
|
|
// DWORD BytesWritten;
|
|
static BeginningOfLine = TRUE;
|
|
static LineCount = 0;
|
|
static TruncateLogFileInProgress = FALSE;
|
|
static LogProblemWarned = FALSE;
|
|
|
|
//
|
|
// If we aren't debugging this functionality, just return.
|
|
//
|
|
if ( DebugFlag != 0 && (AzGlDbFlag & DebugFlag) == 0 ) {
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate a buffer to build the line in.
|
|
// If there isn't already one.
|
|
//
|
|
|
|
length = 0;
|
|
|
|
if ( AzGlLogFileOutputBuffer == NULL ) {
|
|
AzGlLogFileOutputBuffer = (LPSTR) LocalAlloc( 0, MAX_PRINTF_LEN + 1 );
|
|
|
|
if ( AzGlLogFileOutputBuffer == NULL ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle the beginning of a new line.
|
|
//
|
|
//
|
|
|
|
if ( BeginningOfLine ) {
|
|
|
|
//
|
|
// Never print empty lines.
|
|
//
|
|
|
|
if ( Format[0] == '\n' && Format[1] == '\0' ) {
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// If the log file is getting huge,
|
|
// truncate it.
|
|
//
|
|
|
|
if ( AzGlLogFile != INVALID_HANDLE_VALUE &&
|
|
!TruncateLogFileInProgress ) {
|
|
|
|
//
|
|
// Only check every 50 lines,
|
|
//
|
|
|
|
LineCount++;
|
|
if ( LineCount >= 50 ) {
|
|
DWORD FileSize;
|
|
LineCount = 0;
|
|
|
|
//
|
|
// Is the log file too big?
|
|
//
|
|
|
|
FileSize = GetFileSize( AzGlLogFile, NULL );
|
|
if ( FileSize == 0xFFFFFFFF ) {
|
|
(void) DbgPrint( "[NETLOGON] Cannot GetFileSize %ld\n",
|
|
GetLastError );
|
|
} else if ( FileSize > AzGlParameters.LogFileMaxSize ) {
|
|
TruncateLogFileInProgress = TRUE;
|
|
LeaveCriticalSection( &AzGlLogFileCritSect );
|
|
NlOpenDebugFile( TRUE );
|
|
NlPrint(( NL_MISC,
|
|
"Logfile truncated because it was larger than %ld bytes\n",
|
|
AzGlParameters.LogFileMaxSize ));
|
|
EnterCriticalSection( &AzGlLogFileCritSect );
|
|
TruncateLogFileInProgress = FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we're writing to the debug terminal,
|
|
// indicate this is a azroles message.
|
|
//
|
|
|
|
if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
|
|
length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[AZROLES] " );
|
|
}
|
|
|
|
//
|
|
// Put the timestamp at the begining of the line.
|
|
//
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime( &SystemTime );
|
|
length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length],
|
|
"%02u/%02u %02u:%02u:%02u ",
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wHour,
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond );
|
|
}
|
|
#endif // 0
|
|
|
|
//
|
|
// Indicate the type of message on the line
|
|
//
|
|
{
|
|
char *Text;
|
|
|
|
switch (DebugFlag) {
|
|
case AZD_HANDLE:
|
|
Text = "HANDLE"; break;
|
|
case AZD_OBJLIST:
|
|
Text = "OBJLIST"; break;
|
|
case AZD_INVPARM:
|
|
Text = "INVPARM"; break;
|
|
case AZD_PERSIST:
|
|
case AZD_PERSIST_MORE:
|
|
Text = "PERSIST"; break;
|
|
case AZD_REF:
|
|
Text = "REF"; break;
|
|
default:
|
|
Text = "UNKNOWN"; break;
|
|
|
|
case 0:
|
|
Text = NULL;
|
|
}
|
|
if ( Text != NULL ) {
|
|
length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[%s] ", Text );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Put a the information requested by the caller onto the line
|
|
//
|
|
|
|
lengthTmp = (ULONG) _vsnprintf( &AzGlLogFileOutputBuffer[length],
|
|
MAX_PRINTF_LEN - length - 1,
|
|
Format,
|
|
arglist );
|
|
|
|
if ( lengthTmp < 0 ) {
|
|
length = MAX_PRINTF_LEN - 1;
|
|
// always end the line which cannot fit into the buffer
|
|
AzGlLogFileOutputBuffer[length-1] = '\n';
|
|
} else {
|
|
length += lengthTmp;
|
|
}
|
|
|
|
BeginningOfLine = (length > 0 && AzGlLogFileOutputBuffer[length-1] == '\n' );
|
|
if ( BeginningOfLine ) {
|
|
AzGlLogFileOutputBuffer[length-1] = '\r';
|
|
AzGlLogFileOutputBuffer[length] = '\n';
|
|
AzGlLogFileOutputBuffer[length+1] = '\0';
|
|
length++;
|
|
}
|
|
|
|
|
|
#if 0
|
|
//
|
|
// If the log file isn't open,
|
|
// just output to the debug terminal
|
|
//
|
|
|
|
if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
|
|
#if DBG
|
|
if ( !LogProblemWarned ) {
|
|
(void) DbgPrint( "[NETLOGON] Cannot write to log file [Invalid Handle]\n" );
|
|
LogProblemWarned = TRUE;
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Write the debug info to the log file.
|
|
//
|
|
|
|
} else {
|
|
if ( !WriteFile( AzGlLogFile,
|
|
AzGlLogFileOutputBuffer,
|
|
length,
|
|
&BytesWritten,
|
|
NULL ) ) {
|
|
#if DBG
|
|
if ( !LogProblemWarned ) {
|
|
(void) DbgPrint( "[NETLOGON] Cannot write to log file %ld\n", GetLastError() );
|
|
LogProblemWarned = TRUE;
|
|
}
|
|
#endif // DBG
|
|
}
|
|
|
|
}
|
|
#else // 0
|
|
printf( "%s", AzGlLogFileOutputBuffer );
|
|
#endif // 0
|
|
|
|
}
|
|
|
|
VOID
|
|
AzpPrintRoutine(
|
|
IN DWORD DebugFlag,
|
|
IN LPSTR Format,
|
|
...
|
|
)
|
|
|
|
{
|
|
va_list arglist;
|
|
|
|
//
|
|
// vsprintf isn't multithreaded + we don't want to intermingle output
|
|
// from different threads.
|
|
//
|
|
|
|
EnterCriticalSection( &AzGlLogFileCritSect );
|
|
|
|
//
|
|
// Simply change arguments to va_list form and call NlPrintRoutineV
|
|
//
|
|
|
|
va_start(arglist, Format);
|
|
|
|
AzpPrintRoutineV( DebugFlag, Format, arglist );
|
|
|
|
va_end(arglist);
|
|
|
|
LeaveCriticalSection( &AzGlLogFileCritSect );
|
|
|
|
} // AzPrintRoutine
|
|
#endif // AZROLESDBG
|