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

868 lines
23 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dbattr.c
Abstract:
LSA Database Handle Manager - Object Attribute Routines
These routines manipulate or construct LSA Database Object Attributes
or their content.
Author:
Scott Birrell (ScottBi) January 21, 1992
Environment:
Revision History:
--*/
#include <lsapch2.h>
#include "dbp.h"
NTSTATUS
LsapDbMakeUnicodeAttribute(
IN OPTIONAL PUNICODE_STRING UnicodeValue,
IN PUNICODE_STRING AttributeName,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
/*++
Routine Description:
This function constructs Attribute Information for an attribute value
that is in Unicode String form. The Unicode String is converted to
Self-Relative form after validation and the given Attribute
structure is filled in.
If a NULL UnicodeValue, or string of length 0 is specified, NULL is
propagated as the attribute value.
WARNING! - This routine allocates memory for the Self-Relative Unicode
string produced. This memory must be freed after use by calling
MIDL_user_free()
Arguments:
UnicodeValue - Pointer to Unicode String containing the Attribute's
Value. NULL may be specified, in which case, NULL will be stored
in the output Attribute.
AttributeName - Pointer to the Unicode name of the attribute.
Attribute - Pointer to structure that will receive the
attributes's information. This consists of the attribute's name,
value and value length.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources such
as memory to complete the call.
STATUS_INVALID_PARAMETER - The specified AttributeValue is not a
pointer to a Unicode String.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PUNICODE_STRING_SR OutputAttributeValue = NULL;
ULONG OutputAttributeValueLength = 0;
RtlZeroMemory( Attribute, sizeof( LSAP_DB_ATTRIBUTE ) );
//
// Mark attribute initially as not having had memory allocated by
// setting MemoryAllocated to FALSE. If routine succeeds and we allocate
// memory via MIDL_user_allocate() change MemoryAllocated field to TRUE.
//
Attribute->MemoryAllocated = FALSE;
if (ARGUMENT_PRESENT(UnicodeValue) && UnicodeValue->Length != 0) {
//
// Validate the string
//
if ( !LsapValidateLsaUnicodeString( UnicodeValue ) ) {
return STATUS_INVALID_PARAMETER;
}
//
// Calculate the size of memory required for a Self-Relative
// Unicode String and allocate the memory.
//
OutputAttributeValueLength =
sizeof(UNICODE_STRING_SR) + (ULONG) UnicodeValue->MaximumLength;
OutputAttributeValue = MIDL_user_allocate(OutputAttributeValueLength);
if (OutputAttributeValue == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
Attribute->MemoryAllocated = TRUE;
//
// Setup self-relative Unicode String (but with absolute buffer pointer
// referencing buffer following UNICODE_STRING header)
// Copy source Unicode Value to Self-relative Unicode String. Set buffer pointer
// to NULL as it will not be used here.
//
OutputAttributeValue->Length = UnicodeValue->Length;
OutputAttributeValue->MaximumLength = UnicodeValue->MaximumLength;
OutputAttributeValue->Offset = sizeof(UNICODE_STRING_SR);
//
// Copy the Unicode string Buffer
//
RtlCopyMemory( OutputAttributeValue + 1,
UnicodeValue->Buffer,
UnicodeValue->Length );
}
Attribute->AttributeName = AttributeName;
Attribute->AttributeValue = OutputAttributeValue;
Attribute->AttributeValueLength = OutputAttributeValueLength;
return(Status);
}
VOID
LsapDbCopyUnicodeAttributeNoAlloc(
OUT PUNICODE_STRING OutputString,
IN PLSAP_DB_ATTRIBUTE Attribute,
IN BOOLEAN SelfRelative
)
/*++
Routine Description:
This function makes a UNICODE_STRING structure reference the value of
an attribute that has a Unicode String as its value. No memory is allocated
for the attribute values's Unicode Buffer.
Arguments:
OutputString - Pointer to UNICODE_STRING structure that will be made
to reference the attribute value's Unicode Buffer.
Attribute - Pointer to attribute information block whose
AttributeValue field is a pointer to a Unicode String,
or NULL. If NULL or if the string has length 0, the output Unicode
String is initialized with a buffer pointer equal to NULL and a zero
length.
SelfRelative - TRUE if the input Unicode String is expected to be
in Self-Relative form, else FALSE.
Returns:
Nothing
--*/
{
UNICODE_STRING AbsInputUnicodeString;
PUNICODE_STRING InputUnicodeString;
PUNICODE_STRING ReturnedUnicodeString = NULL;
//
// The Length field will be accessed before we know whether we have
// a self-relative string structure.
//
C_ASSERT( FIELD_OFFSET( UNICODE_STRING, Length ) ==
FIELD_OFFSET( UNICODE_STRING_SR, Length ));
//
// Obtain pointer to input Unicode String contained in Attribute.
// Convert it to absolute form if necessary.
//
InputUnicodeString = (PUNICODE_STRING) Attribute->AttributeValue;
if ((InputUnicodeString != NULL) && (InputUnicodeString->Length != 0)) {
if (SelfRelative) {
PUNICODE_STRING_SR InputUnicodeStringSr;
InputUnicodeStringSr =
(PUNICODE_STRING_SR) Attribute->AttributeValue;
AbsInputUnicodeString.Length = InputUnicodeStringSr->Length;
AbsInputUnicodeString.MaximumLength =
InputUnicodeStringSr->MaximumLength;
AbsInputUnicodeString.Buffer =
(PWSTR)
(((PUCHAR)(InputUnicodeStringSr)) +
InputUnicodeStringSr->Offset);
InputUnicodeString = &AbsInputUnicodeString;
}
OutputString->Buffer = InputUnicodeString->Buffer;
OutputString->Length = InputUnicodeString->Length;
OutputString->MaximumLength = InputUnicodeString->MaximumLength;
} else {
//
// The attribute contains a NULL Unicode String or one of length
// 0. Set the output Unicode String to NULL.
//
OutputString->Length = OutputString->MaximumLength = 0;
OutputString->Buffer = (PWSTR) NULL;
}
}
NTSTATUS
LsapDbCopyUnicodeAttribute(
OUT PUNICODE_STRING OutputString,
IN PLSAP_DB_ATTRIBUTE Attribute,
IN BOOLEAN SelfRelative
)
/*++
Routine Description:
This function makes a UNICODE_STRING structure reference the value of
an attribute that has a Unicode String as its value. Memory for the
attribute values's Unicode Buffer is allocated via MIDL_user_allocate.
Arguments:
OutputString - Pointer to UNICODE_STRING structure that will be made
to reference the attribute value's Unicode Buffer.
Attribute - Pointer to attribute information block whose
AttributeValue field is a pointer to a Unicode String,
or NULL. If NULL or if the string has length 0, the output Unicode String is initialized
with a buffer pointer equal to NULL and a zero length.
SelfRelative - TRUE if the input Unicode String is expected to be
in Self-Relative form, else FALSE.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_SUCCESS - The call was successful
STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
such as memory to complete the call.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING AbsInputUnicodeString;
PUNICODE_STRING InputUnicodeString;
PUNICODE_STRING_SR InputUnicodeStringSr;
PUNICODE_STRING ReturnedUnicodeString = NULL;
//
// The Length field will be accessed before we know whether we have
// a self-relative string structure.
//
C_ASSERT( FIELD_OFFSET( UNICODE_STRING, Length ) ==
FIELD_OFFSET( UNICODE_STRING_SR, Length ));
//
// Obtain pointer to input Unicode String contained in Attribute.
// Convert it to absolute form if necessary.
//
InputUnicodeString = (PUNICODE_STRING) Attribute->AttributeValue;
if ((InputUnicodeString != NULL) && (InputUnicodeString->Length != 0)) {
if (SelfRelative) {
InputUnicodeStringSr =
(PUNICODE_STRING_SR) Attribute->AttributeValue;
AbsInputUnicodeString.Length = InputUnicodeStringSr->Length;
AbsInputUnicodeString.MaximumLength =
InputUnicodeStringSr->MaximumLength;
AbsInputUnicodeString.Buffer =
(PWSTR)
(((PUCHAR)(InputUnicodeStringSr)) +
InputUnicodeStringSr->Offset);
InputUnicodeString = &AbsInputUnicodeString;
}
//
// Now allocate memory for the Unicode String Buffer.
//
OutputString->Buffer =
MIDL_user_allocate(InputUnicodeString->MaximumLength);
if (OutputString->Buffer == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Initialize UNICODE_STRING header
//
OutputString->Length = InputUnicodeString->Length;
OutputString->MaximumLength = InputUnicodeString->MaximumLength;
//
// Copy the input Unicode String
//
RtlCopyUnicodeString( OutputString, InputUnicodeString );
} else {
//
// The attribute contains a NULL Unicode String or one of length
// 0. Set the output Unicode String to NULL.
//
OutputString->Length = OutputString->MaximumLength = 0;
OutputString->Buffer = (PWSTR) NULL;
}
return(Status);
}
NTSTATUS
LsapDbMakeSidAttribute(
IN OPTIONAL PSID Sid,
IN PUNICODE_STRING AttributeName,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
/*++
Routine Description:
This function constructs Attribute Information for an attribute value
that is in Sid form. The Sid is validated and the given
Attribute structure is filled in.
Arguments:
Sid - Pointer to the Sid or NULL.
AttributeName - Pointer to the Unicode name of the attribute.
Attribute - Pointer to structure that will receive the
attributes's information. This consists of the attribute's name,
value and value length.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INVALID_PARAMETER - The specified AttributeValue is not a
pointer to a syntactically valid Sid, or NULL.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RtlZeroMemory( Attribute, sizeof( LSAP_DB_ATTRIBUTE ) );
Attribute->AttributeName = AttributeName;
Attribute->MemoryAllocated = FALSE;
if (ARGUMENT_PRESENT(Sid)) {
if (RtlValidSid(Sid)) {
Attribute->AttributeValue = Sid;
Attribute->AttributeValueLength = RtlLengthSid(Sid);
return(Status);
}
Status = STATUS_INVALID_PARAMETER;
}
//
// The supplied Sid is NULL or invalid.
//
Attribute->AttributeValue = NULL;
Attribute->AttributeValueLength = 0;
return(Status);
}
NTSTATUS
LsapDbMakeGuidAttribute(
IN OPTIONAL GUID *Guid,
IN PUNICODE_STRING AttributeName,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
/*++
Routine Description:
This function constructs Attribute Information for an attribute value
that is in GUID form. The given Attribute structure is filled in.
Arguments:
Guid - Pointer to the GUID or NULL.
AttributeName - Pointer to the Unicode name of the attribute.
Attribute - Pointer to structure that will receive the
attributes's information. This consists of the attribute's name,
value and value length.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INVALID_PARAMETER - The specified AttributeValue is not a
pointer to a syntactically valid Sid, or NULL.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RtlZeroMemory( Attribute, sizeof( LSAP_DB_ATTRIBUTE ) );
Attribute->AttributeName = AttributeName;
Attribute->MemoryAllocated = FALSE;
if (ARGUMENT_PRESENT(Guid)) {
Attribute->AttributeValue = Guid;
Attribute->AttributeValueLength = sizeof(GUID);
return(Status);
}
//
// The supplied GUID is NULL
//
Attribute->AttributeValue = NULL;
Attribute->AttributeValueLength = 0;
return(Status);
}
NTSTATUS
LsapDbReadAttribute(
IN LSAPR_HANDLE ObjectHandle,
IN OUT PLSAP_DB_ATTRIBUTE Attribute
)
/*++
Routine Description:
This function reads an attribute of an object, allocating memory if
requested for the buffer containing the attribute's value.
Arguments:
ObjectHandle - Handle to object obtained from LsapDbCreateObject or
LsapDbOpenObject
Attributes - Pointer to an array of Attribute Information blocks each
containing pointers to the attribute's Unicode Name, an optional
pointer to a buffer that will receive the value and an optional
length of the value expected in bytes.
If the AttributeValue field in this structure is specified as non-NULL,
the attribute's data will be returned in the specified buffer. In
this case, the AttributeValueLength field must specify a sufficiently
large buffer size in bytes. If the specified size is too small,
a warning is returned and the buffer size required is returned in
AttributeValueLength.
If the AttributeValue field in this structure is NULL, the routine
will allocate memory for the attribute value's buffer, via MIDL_user_allocate(). If
the AttributeValueLength field is non-zero, the number of bytes specified
will be allocated. If the size of buffer allocated is too small to
hold the attribute's value, a warning is returned. If the
AttributeValuelength field is 0, the routine will first query the size
of buffer required and then allocate its memory.
In all success cases and buffer overflow cases, the
AttributeValueLength is set upon exit to the size of data required.
Return Value:
NTSTATUS - Standard Nt Result Code
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
LSAP_DB_ATTRIBUTE DsAttribute;
if (Attribute->AttributeValue != NULL) {
if (Attribute->AttributeValueLength == 0) {
return(STATUS_INVALID_PARAMETER);
}
}
//
// Deal with the Ds case seperately
//
if ( LsapDsIsWriteDs( ObjectHandle ) &&
Attribute->DbNameIndex != SecDesc ) {
RtlCopyMemory( &DsAttribute, Attribute, sizeof( LSAP_DB_ATTRIBUTE ) );
//
// Now, do the read...
//
Status = LsapDsReadAttributes( &((LSAP_DB_HANDLE)ObjectHandle)->PhysicalNameDs,
LSAPDS_OP_NO_LOCK,
&DsAttribute,
1 );
if ( NT_SUCCESS( Status ) ) {
Attribute->AttributeValueLength = DsAttribute.AttributeValueLength;
if ( Attribute->AttributeValue != NULL ) {
if ( Attribute->AttributeValueLength >= DsAttribute.AttributeValueLength ) {
RtlCopyMemory( Attribute->AttributeValue, DsAttribute.AttributeValue,
DsAttribute.AttributeValueLength );
} else {
Status = STATUS_BUFFER_OVERFLOW;
}
} else {
Attribute->AttributeValue = DsAttribute.AttributeValue;
DsAttribute.AttributeValue = NULL;
}
MIDL_user_free( DsAttribute.AttributeValue );
}
return( Status );
}
Attribute->MemoryAllocated = FALSE;
//
// If an explicit buffer pointer is given, verify that the length
// specified is non-zero and attempt to use that buffer.
//
if (Attribute->AttributeValue != NULL) {
if (Attribute->AttributeValueLength == 0) {
return(STATUS_INVALID_PARAMETER);
}
Status = LsapDbReadAttributeObject(
ObjectHandle,
Attribute->AttributeName,
Attribute->AttributeValue,
&Attribute->AttributeValueLength
);
if (!NT_SUCCESS(Status)) {
goto ReadAttributeError;
}
return(Status);
}
//
// No output buffer pointer has been given. If a zero buffer
// size is given, query size of memory required. Since the
// buffer length is 0, STATUS_SUCCESS should be returned rather
// than STATUS_BUFFER_OVERFLOW.
//
if (Attribute->AttributeValueLength == 0) {
Status = LsapDbReadAttributeObject(
ObjectHandle,
Attribute->AttributeName,
NULL,
&Attribute->AttributeValueLength
);
if (!NT_SUCCESS(Status)) {
goto ReadAttributeError;
}
Status = STATUS_SUCCESS;
}
//
// If the attribute value size needed is 0, return NULL pointer
//
if (Attribute->AttributeValueLength == 0) {
Attribute->AttributeValue = NULL;
return(STATUS_SUCCESS);
}
//
// Allocate memory for the buffer.
//
Attribute->AttributeValue =
MIDL_user_allocate(Attribute->AttributeValueLength);
if (Attribute->AttributeValue == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ReadAttributeError;
}
Attribute->MemoryAllocated = TRUE;
//
// Now read the attribute into the buffer.
//
Status = LsapDbReadAttributeObject(
ObjectHandle,
Attribute->AttributeName,
Attribute->AttributeValue,
&Attribute->AttributeValueLength
);
if (!NT_SUCCESS(Status)) {
goto ReadAttributeError;
}
ReadAttributeFinish:
return(Status);
ReadAttributeError:
//
// If memory was allocated for any values read, it must be freed.
//
if (Attribute->MemoryAllocated) {
MIDL_user_free( Attribute->AttributeValue );
}
goto ReadAttributeFinish;
}
NTSTATUS
LsapDbFreeAttributes(
IN ULONG Count,
IN PLSAP_DB_ATTRIBUTE Attributes
)
/*++
Routine Description:
This function frees memory allocated for Attribute Values in an
array of attributes.
Arguments:
Count - Count of attributes in the array
Attributes - Pointer to array of attributes. Only those attributes
in which MemoryAllocated is set to TRUE will have their
Attribute Value buffers freed. For these attributes, MemoryAllocated
will be set to false.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG Index;
for (Index = 0; Index < Count; Index++) {
if (Attributes[Index].MemoryAllocated) {
MIDL_user_free(Attributes[Index].AttributeValue);
Attributes[Index].MemoryAllocated = FALSE;
Attributes[Index].AttributeValue = NULL;
Attributes[Index].AttributeValueLength = 0;
}
}
return(Status);
}
NTSTATUS
LsapDbMakeUnicodeAttributeDs(
IN OPTIONAL PUNICODE_STRING UnicodeValue,
IN LSAP_DB_NAMES Name,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
{
NTSTATUS Status = LsapDbMakeUnicodeAttribute( UnicodeValue,
&LsapDbNames[Name],
Attribute );
if ( NT_SUCCESS( Status ) ) {
Attribute->DsAttId = LsapDbDsAttInfo[Name].AttributeId;
Attribute->AttribType = LsapDbDsAttInfo[Name].AttributeType;
Attribute->DbNameIndex = Name;
}
return( Status );
}
NTSTATUS
LsapDbMakeSidAttributeDs(
IN PSID Sid,
IN IN LSAP_DB_NAMES Name,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
{
NTSTATUS Status = LsapDbMakeSidAttribute( Sid,
&LsapDbNames[Name],
Attribute );
if ( NT_SUCCESS( Status ) ) {
Attribute->DsAttId = LsapDbDsAttInfo[Name].AttributeId;
Attribute->AttribType = LsapDbDsAttInfo[Name].AttributeType;
Attribute->DbNameIndex = Name;
}
return( Status );
}
NTSTATUS
LsapDbMakeGuidAttributeDs(
IN GUID *Guid,
IN LSAP_DB_NAMES Name,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
{
NTSTATUS Status = LsapDbMakeGuidAttribute( Guid,
&LsapDbNames[Name],
Attribute );
if ( NT_SUCCESS( Status ) ) {
Attribute->DsAttId = LsapDbDsAttInfo[Name].AttributeId;
Attribute->AttribType = LsapDbDsAttInfo[Name].AttributeType;
Attribute->DbNameIndex = Name;
}
return( Status );
}
NTSTATUS
LsapDbMakePByteAttributeDs(
IN OPTIONAL PBYTE Buffer,
IN ULONG BufferLength,
IN LSAP_DB_ATTRIB_TYPE AttribType,
IN PUNICODE_STRING AttributeName,
OUT PLSAP_DB_ATTRIBUTE Attribute
)
/*++
Routine Description:
This function constructs Attribute Information for an attribute value
that is in Sid form. The Sid is validated and the given
Attribute structure is filled in.
Arguments:
Sid - Pointer to the Sid or NULL.
AttributeName - Pointer to the Unicode name of the attribute.
Attribute - Pointer to structure that will receive the
attributes's information. This consists of the attribute's name,
value and value length.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INVALID_PARAMETER - The specified AttributeValue is not a
pointer to a syntactically valid Sid, or NULL.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
Attribute->AttributeName = AttributeName;
Attribute->MemoryAllocated = FALSE;
if (ARGUMENT_PRESENT(Buffer)) {
Attribute->AttributeValue = Buffer;
Attribute->AttributeValueLength = BufferLength;
} else {
//
// The supplied Sid is NULL or invalid.
//
Attribute->AttributeValue = NULL;
Attribute->AttributeValueLength = 0;
}
Attribute->DsAttId = LsapDbDsAttInfo[Name].AttributeId;
Attribute->AttribType = AttribType;
Attribute->DbNameIndex = Name;
return(Status);
}