Windows-Server-2003/ds/security/azroles/op.cxx

740 lines
18 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
op.cxx
Abstract:
Routines implementing the Operation object
Author:
Cliff Van Dyke (cliffv) 11-Apr-2001
--*/
#include "pch.hxx"
//
// Define the default values for all scalar attributes
//
ULONG AzGlDefOperationId = 0;
AZP_DEFAULT_VALUE AzGlOperationDefaultValues[] = {
{ AZ_PROP_OPERATION_ID, AZ_DIRTY_OPERATION_ID, &AzGlDefOperationId },
{ 0, 0, NULL }
};
DWORD
AzpOperationInit(
IN PGENERIC_OBJECT ParentGenericObject,
IN PGENERIC_OBJECT ChildGenericObject
)
/*++
Routine Description:
This routine is a worker routine for AzOperationCreate. It does any object specific
initialization that needs to be done.
On entry, AzGlResource must be locked exclusively.
Arguments:
ParentGenericObject - Specifies the parent object to add the child object onto.
The reference count has been incremented on this object.
ChildGenericObject - Specifies the newly allocated child object.
The reference count has been incremented on this object.
Return Value:
NO_ERROR - The operation was successful
ERROR_NOT_ENOUGH_MEMORY - not enough memory
Other exception status codes
--*/
{
PAZP_OPERATION Operation = (PAZP_OPERATION) ChildGenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Sanity check the parent
//
ASSERT( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION );
UNREFERENCED_PARAMETER( ParentGenericObject );
//
// Operations are referenced by "Tasks" and "Roles"
// Let the generic object manager know all of the lists we support
// This is a "back" link so we don't need to define which tasks can reference this operation.
//
ChildGenericObject->GenericObjectLists = &Operation->backTasks;
// Back link to tasks
ObInitObjectList( &Operation->backTasks,
&Operation->backRoles,
TRUE, // Backward link
0, // No link pair id
0, // No dirty bit on back link
NULL,
NULL,
NULL );
// Back link to roles
ObInitObjectList( &Operation->backRoles,
NULL,
TRUE, // Backward link
0, // No link pair id
0, // No dirty bit on back link
NULL,
NULL,
NULL );
return NO_ERROR;
}
VOID
AzpOperationFree(
IN PGENERIC_OBJECT GenericObject
)
/*++
Routine Description:
This routine is a worker routine for Operation object free. It does any object specific
cleanup that needs to be done.
On entry, AzGlResource must be locked exclusively.
Arguments:
GenericObject - Specifies a pointer to the object to be deleted.
Return Value:
None
--*/
{
// PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
UNREFERENCED_PARAMETER( GenericObject );
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Free any local strings
//
}
DWORD
AzpOperationNameConflict(
IN PGENERIC_OBJECT ParentGenericObject,
IN PAZP_STRING ChildObjectNameString
)
/*++
Routine Description:
This routine is a worker routine to determine if the specified ChildObjectNameString
conflicts with the names of other objects that share a namespace with Operations.
On entry, AzGlResource must be locked exclusively.
Arguments:
ParentGenericObject - Specifies the parent object to add the child object onto.
The reference count has been incremented on this object.
ChildObjectNameString - Specifies the name of the child object.
Return Value:
NO_ERROR - The operation was successful
ERROR_ALREADY_EXISTS - An object by that name already exists
--*/
{
ULONG WinStatus;
PAZP_APPLICATION Application = (PAZP_APPLICATION) ParentGenericObject;
PGENERIC_OBJECT ConflictGenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Sanity check the parent
//
ASSERT( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION );
//
// Operations and tasks share a namespace so ensure there isn't a task by this name.
//
WinStatus = ObReferenceObjectByName( &Application->Tasks,
ChildObjectNameString,
0, // No special flags
&ConflictGenericObject );
if ( WinStatus == NO_ERROR ) {
ObDereferenceObject( ConflictGenericObject );
return ERROR_ALREADY_EXISTS;
}
//
// Check tasks that are children of child scopes.
//
WinStatus = ObCheckNameConflict( &Application->Scopes,
ChildObjectNameString,
offsetof(_AZP_SCOPE, Tasks),
0,
0 );
return WinStatus;
}
DWORD
AzpOperationGetProperty(
IN PGENERIC_OBJECT GenericObject,
IN ULONG Flags,
IN ULONG PropertyId,
OUT PVOID *PropertyValue
)
/*++
Routine Description:
This routine is the Group specific worker routine for AzGetProperty.
It does any object specific property gets.
On entry, AzGlResource must be locked shared.
Arguments:
GenericObject - Specifies a pointer to the object to be queried
Flags - Specifies internal flags
AZP_FLAGS_BY_GUID - name lists should be returned as GUID lists
AZP_FLAGS_PERSIST_* - Call is from the persistence provider
PropertyId - Specifies which property to return.
PropertyValue - Specifies a pointer to return the property in.
The returned pointer must be freed using AzFreeMemory.
The returned value and type depends in PropertyId. The valid values are:
AZ_PROP_OPERATION_ID PULONG - Operation ID of the operation
Return Value:
Status of the operation
--*/
{
DWORD WinStatus = NO_ERROR;
PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
UNREFERENCED_PARAMETER(Flags); //ignore
//
// Initialization
//
ASSERT( AzpIsLockedShared( &AzGlResource ) );
//
// Return any object specific attribute
//
// Return operation id to the caller
//
switch ( PropertyId ) {
case AZ_PROP_OPERATION_ID:
*PropertyValue = AzpGetUlongProperty( Operation->OperationId );
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
break;
default:
AzPrint(( AZD_INVPARM, "AzpOperationGetProperty: invalid prop id %ld\n", PropertyId ));
WinStatus = ERROR_INVALID_PARAMETER;
break;
}
return WinStatus;
}
DWORD
AzpOperationSetProperty(
IN PGENERIC_OBJECT GenericObject,
IN ULONG Flags,
IN ULONG PropertyId,
IN PVOID PropertyValue
)
/*++
Routine Description:
This routine is the Operation object specific worker routine for AzSetProperty.
It does any object specific property sets.
On entry, AzGlResource must be locked exclusive.
Arguments:
GenericObject - Specifies a pointer to the object to be modified
Flags - Specifies flags controlling to operation of the routine
AZP_FLAGS_SETTING_TO_DEFAULT - Property is being set to default value
AZP_FLAGS_PERSIST_* - Call is from the persistence provider
PropertyId - Specifies which property to set.
PropertyValue - Specifies a pointer to the property.
The specified value and type depends in PropertyId. The valid values are:
AZ_PROP_OPERATION_ID PULONG - Operation ID of the operation
Return Value:
Status of the operation
--*/
{
DWORD WinStatus;
PAZP_OPERATION Operation = (PAZP_OPERATION) GenericObject;
PAZP_OPERATION ReferencedOperation = NULL;
LONG TempLong;
BOOL bHasChanged = TRUE;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Return any object specific attribute
//
// Return ooperation id to the caller
//
switch ( PropertyId ) {
case AZ_PROP_OPERATION_ID:
BEGIN_SETPROP( &WinStatus, Operation, Flags, AZ_DIRTY_OPERATION_ID ) {
WinStatus = AzpCaptureLong( PropertyValue, &TempLong );
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
if ( TempLong < 0) {
AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: Operation Id too small %ld\n", TempLong ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Ensure the operation id doesn't collide with another operation
//
WinStatus = AzpReferenceOperationByOpId(
(PAZP_APPLICATION)ParentOfChild( GenericObject ),
TempLong,
FALSE,
&ReferencedOperation );
if ( WinStatus == NO_ERROR ) {
if ( ReferencedOperation != Operation ) {
AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: Operation ID %ld is already used.\n", TempLong ));
WinStatus = ERROR_ALREADY_EXISTS;
goto Cleanup;
}
//
// Allow setting our own operation ID back to its original value
//
WinStatus = ERROR_NOT_FOUND;
}
if ( WinStatus != ERROR_NOT_FOUND ) {
goto Cleanup;
}
} END_VALIDITY_CHECKING;
//
// Set the operation ID on the object
//
Operation->OperationId = TempLong;
WinStatus = NO_ERROR;
} END_SETPROP(bHasChanged);
break;
default:
AzPrint(( AZD_INVPARM, "AzpOperationSetProperty: invalid prop id %ld\n", PropertyId ));
WinStatus = ERROR_INVALID_PARAMETER;
break;
}
Cleanup:
if ( ReferencedOperation != NULL ) {
ObDereferenceObject( (PGENERIC_OBJECT)ReferencedOperation );
}
return WinStatus;
}
DWORD
AzpReferenceOperationByOpId(
IN PAZP_APPLICATION Application,
IN LONG OperationId,
IN BOOLEAN RefreshCache,
OUT PAZP_OPERATION *RetOperation
)
/*++
Routine Description
This routine finds an operation object by the operationid
On entry, AzGlResource must be locked shared.
Arguments
Application - Application that the operation is defined for
OperationId - Operation id to look for
RefreshCache - If TRUE, the returned object has its cache entry refreshed from
the policy database if needed.
If FALSE, the entry is returned unrefreshed.
RetOperation - On success, returns a pointer to the operation object
The returned pointer must be dereferenced using ObDereferenceObject.
Return Value
NO_ERROR: The object was returned
ERROR_NOT_FOUND: The object could not be found
Others: The object could not be refreshed
--*/
{
DWORD WinStatus;
PGENERIC_OBJECT GenericObject;
PAZP_OPERATION Operation;
PLIST_ENTRY ListEntry;
PGENERIC_OBJECT_HEAD GenericObjectHead = &Application->Operations;
//
// Initialization
//
ASSERT( AzpIsLockedShared( &AzGlResource ) );
*RetOperation = NULL;
//
// Loop trying to find the object
//
// ??? Consider doing a binary search. That would be possible if we maintained
// a separate list sorted by operation id
//
for ( ListEntry = GenericObjectHead->Head.Flink ;
ListEntry != &GenericObjectHead->Head ;
ListEntry = ListEntry->Flink) {
GenericObject = CONTAINING_RECORD( ListEntry,
GENERIC_OBJECT,
Next );
Operation = (PAZP_OPERATION) GenericObject;
//
// Ignore deleted objects
//
if ( GenericObject->Flags & GENOBJ_FLAGS_DELETED ) {
continue;
}
//
// If we found the object,
// grab a reference.
//
if ( Operation->OperationId == OperationId ) {
//
// If the caller wants the object to be refreshed,
// do so now.
//
if ( RefreshCache &&
(GenericObject->Flags & GENOBJ_FLAGS_REFRESH_ME) != 0 ) {
//
// Need exclusive access
//
AzpLockResourceSharedToExclusive( &AzGlResource );
WinStatus = AzPersistRefresh( GenericObject );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
}
//
// Return the object to the caller
//
InterlockedIncrement( &GenericObject->ReferenceCount );
AzpDumpGoRef( "Ref by operation id", GenericObject );
*RetOperation = Operation;
return NO_ERROR;
}
}
return ERROR_NOT_FOUND;
}
DWORD
WINAPI
AzOperationCreate(
IN AZ_HANDLE ApplicationHandle,
IN LPCWSTR OperationName,
IN DWORD Reserved,
OUT PAZ_HANDLE OperationHandle
)
/*++
Routine Description:
This routine adds an operation into the scope of the specified application.
Arguments:
ApplicationHandle - Specifies a handle to the application.
OperationName - Specifies the name of the operation to add.
Reserved - Reserved. Must by zero.
OperationHandle - Return a handle to the operation.
The caller must close this handle by calling AzCloseHandle.
Return Value:
NO_ERROR - The operation was successful
ERROR_ALREADY_EXISTS - An object by that name already exists
--*/
{
//
// Call the common routine to do most of the work
//
return ObCommonCreateObject(
(PGENERIC_OBJECT) ApplicationHandle,
OBJECT_TYPE_APPLICATION,
&(((PAZP_APPLICATION)ApplicationHandle)->Operations),
OBJECT_TYPE_OPERATION,
OperationName,
Reserved,
(PGENERIC_OBJECT *) OperationHandle );
}
DWORD
WINAPI
AzOperationOpen(
IN AZ_HANDLE ApplicationHandle,
IN LPCWSTR OperationName,
IN DWORD Reserved,
OUT PAZ_HANDLE OperationHandle
)
/*++
Routine Description:
This routine opens an operation into the scope of the specified application.
Arguments:
ApplicationHandle - Specifies a handle to the application.
OperationName - Specifies the name of the operation to open
Reserved - Reserved. Must by zero.
OperationHandle - Return a handle to the operation.
The caller must close this handle by calling AzCloseHandle.
Return Value:
NO_ERROR - The operation was successful
ERROR_NOT_FOUND - There is no operation by that name
--*/
{
//
// Call the common routine to do most of the work
//
return ObCommonOpenObject(
(PGENERIC_OBJECT) ApplicationHandle,
OBJECT_TYPE_APPLICATION,
&(((PAZP_APPLICATION)ApplicationHandle)->Operations),
OBJECT_TYPE_OPERATION,
OperationName,
Reserved,
(PGENERIC_OBJECT *) OperationHandle );
}
DWORD
WINAPI
AzOperationEnum(
IN AZ_HANDLE ApplicationHandle,
IN DWORD Reserved,
IN OUT PULONG EnumerationContext,
OUT PAZ_HANDLE OperationHandle
)
/*++
Routine Description:
Enumerates all of the operations for the specified application.
Arguments:
ApplicationHandle - Specifies a handle to the application.
Reserved - Reserved. Must by zero.
EnumerationContext - Specifies a context indicating the next operation to return
On input for the first call, should point to zero.
On input for subsequent calls, should point to the value returned on the previous call.
On output, returns a value to be passed on the next call.
OperationHandle - Returns a handle to the next operation object.
The caller must close this handle by calling AzCloseHandle.
Return Value:
NO_ERROR - The operation was successful (a handle was returned)
ERROR_NO_MORE_ITEMS - No more items were available for enumeration
--*/
{
//
// Call the common routine to do most of the work
//
return ObCommonEnumObjects(
(PGENERIC_OBJECT) ApplicationHandle,
OBJECT_TYPE_APPLICATION,
&(((PAZP_APPLICATION)ApplicationHandle)->Operations),
EnumerationContext,
Reserved,
(PGENERIC_OBJECT *) OperationHandle );
}
DWORD
WINAPI
AzOperationDelete(
IN AZ_HANDLE ApplicationHandle,
IN LPCWSTR OperationName,
IN DWORD Reserved
)
/*++
Routine Description:
This routine deletes an operation from the scope of the specified application.
Also deletes any child objects of OperationName.
Arguments:
ApplicationHandle - Specifies a handle to the application.
OperationName - Specifies the name of the operation to delete.
Reserved - Reserved. Must by zero.
Return Value:
NO_ERROR - The operation was successful
ERROR_NOT_FOUND - An object by that name cannot be found
--*/
{
//
// Call the common routine to do most of the work
//
return ObCommonDeleteObject(
(PGENERIC_OBJECT) ApplicationHandle,
OBJECT_TYPE_APPLICATION,
&(((PAZP_APPLICATION)ApplicationHandle)->Operations),
OBJECT_TYPE_OPERATION,
OperationName,
Reserved );
}