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.
 
 
 
 
 
 

1412 lines
39 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
task.cxx
Abstract:
Routines implementing the Task object
Author:
Cliff Van Dyke (cliffv) 11-Apr-2001
--*/
#include "pch.hxx"
//
// Define the default values for all scalar attributes
//
BOOL AzGlDefIsRoleDefinition = FALSE;
AZP_DEFAULT_VALUE AzGlTaskDefaultValues[] = {
{ AZ_PROP_TASK_BIZRULE, AZ_DIRTY_TASK_BIZRULE, NULL },
{ AZ_PROP_TASK_BIZRULE_LANGUAGE, AZ_DIRTY_TASK_BIZRULE_LANGUAGE, NULL },
{ AZ_PROP_TASK_BIZRULE_IMPORTED_PATH, AZ_DIRTY_TASK_BIZRULE_IMPORTED_PATH, NULL },
{ AZ_PROP_TASK_IS_ROLE_DEFINITION, AZ_DIRTY_TASK_IS_ROLE_DEFINITION, &AzGlDefIsRoleDefinition },
{ 0, 0, NULL }
};
DWORD
AzpTaskInit(
IN PGENERIC_OBJECT ParentGenericObject,
IN PGENERIC_OBJECT ChildGenericObject
)
/*++
Routine Description:
This routine is a worker routine for AzTaskCreate. 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
--*/
{
DWORD WinStatus;
NTSTATUS Status;
PAZP_TASK Task = (PAZP_TASK) ChildGenericObject;
PAZP_APPLICATION Application = NULL;
PAZP_SCOPE Scope = NULL;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Behave differently depending on the object type of the parent object
//
if ( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION ) {
Application = (PAZP_APPLICATION) ParentGenericObject;
} else if ( ParentGenericObject->ObjectType == OBJECT_TYPE_SCOPE ) {
Application = (PAZP_APPLICATION) ParentOfChild( ParentGenericObject );
Scope = (PAZP_SCOPE) ParentGenericObject;
} else {
ASSERT( FALSE );
}
//
// Tasks reference 'Operations' that are children of the same 'Application' as the Task object
// Tasks reference 'Tasks' that are children of the same 'Application' as the Task object
// Let the generic object manager know all of the lists we support
//
ChildGenericObject->GenericObjectLists = &Task->Operations,
// Link to Operations
ObInitObjectList( &Task->Operations,
&Task->Tasks,
FALSE, // Forward link
0, // No link pair id
AZ_DIRTY_TASK_OPERATIONS,
&Application->Operations,
NULL,
NULL );
// Link to Tasks
ObInitObjectList( &Task->Tasks,
&Task->backRoles,
FALSE, // Forward link
0, // No link pair id
AZ_DIRTY_TASK_TASKS,
&Application->Tasks,
Scope == NULL ? NULL : &Scope->Tasks,
NULL );
// Back link to roles
ObInitObjectList( &Task->backRoles,
&Task->backTasks,
TRUE, // Backward link
0, // No link pair id
0, // No dirty bit on back link
NULL,
NULL,
NULL );
// Back link to tasks
ObInitObjectList( &Task->backTasks,
NULL,
TRUE, // Backward link
0, // No link pair id
0, // No dirty bit on back link
NULL,
NULL,
NULL );
//
// Initialize the list of free script engines
//
InitializeListHead( &Task->FreeScriptHead );
//
// Initialize the list of Running script engines
//
Status = SafeInitializeCriticalSection( &Task->RunningScriptCritSect, SAFE_RUNNING_SCRIPT_LIST );
if ( !NT_SUCCESS( Status )) {
WinStatus = RtlNtStatusToDosError( Status );
goto Cleanup;
}
Task->RunningScriptCritSectInitialized = TRUE;
InitializeListHead( &Task->RunningScriptHead );
WinStatus = NO_ERROR;
Cleanup:
if ( WinStatus != NO_ERROR ) {
AzpTaskFree( ChildGenericObject );
}
return WinStatus;
}
VOID
AzpTaskFree(
IN PGENERIC_OBJECT GenericObject
)
/*++
Routine Description:
This routine is a worker routine for Task 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_TASK Task = (PAZP_TASK) GenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Free any local strings
//
AzpFreeString( &Task->BizRule );
AzpFreeString( &Task->BizRuleLanguage );
AzpFreeString( &Task->BizRuleImportedPath );
//
// Free the running script list
//
if ( Task->RunningScriptCritSectInitialized ) {
//
// Free the Free Script List itself
//
AzpFlushBizRule( Task );
//
// The task object is referenced as long as the script is running
// So we shouldn't be here unless the running script list is empty.
ASSERT( IsListEmpty( &Task->RunningScriptHead ));
// Free the crit sect protecting the list
SafeDeleteCriticalSection( &Task->RunningScriptCritSect );
Task->RunningScriptCritSectInitialized = FALSE;
}
}
DWORD
AzpTaskNameConflict(
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 Tasks.
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 = NULL;
PGENERIC_OBJECT ConflictGenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Behave differently depending on the object type of the parent object
//
//
// A task that is a child of an application
// cannot have the same name as any tasks that are children of any of the child scopes.
//
if ( ParentGenericObject->ObjectType == OBJECT_TYPE_APPLICATION ) {
Application = (PAZP_APPLICATION) ParentGenericObject;
//
// Check tasks that are children of child scopes.
//
WinStatus = ObCheckNameConflict( &Application->Scopes,
ChildObjectNameString,
offsetof(_AZP_SCOPE, Tasks),
0,
0 );
//
// A task that is a child of a scope,
// cannot have the same name as tasks that are children of the application.
//
} else if ( ParentGenericObject->ObjectType == OBJECT_TYPE_SCOPE ) {
Application = (PAZP_APPLICATION) ParentOfChild( ParentGenericObject );
//
// Check tasks that are children of the application.
//
WinStatus = ObReferenceObjectByName( &Application->Tasks,
ChildObjectNameString,
0, // No special flags
&ConflictGenericObject );
if ( WinStatus == NO_ERROR ) {
ObDereferenceObject( ConflictGenericObject );
WinStatus = ERROR_ALREADY_EXISTS;
} else {
WinStatus = NO_ERROR;
}
} else {
WinStatus = ERROR_INTERNAL_ERROR;
ASSERT( FALSE );
}
//
// Tasks and operations share a namespace so ensure there isn't an operation by this name.
//
if ( WinStatus == NO_ERROR ) {
WinStatus = ObReferenceObjectByName( &Application->Operations,
ChildObjectNameString,
0, // No special flags
&ConflictGenericObject );
if ( WinStatus == NO_ERROR ) {
ObDereferenceObject( ConflictGenericObject );
WinStatus = ERROR_ALREADY_EXISTS;
} else {
WinStatus = NO_ERROR;
}
}
return WinStatus;
}
DWORD
AzpTaskGetProperty(
IN PGENERIC_OBJECT GenericObject,
IN ULONG Flags,
IN ULONG PropertyId,
OUT PVOID *PropertyValue
)
/*++
Routine Description:
This routine is the Task 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
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_TASK_BIZRULE LPWSTR - Biz rule for the task
AZ_PROP_TASK_BIZRULE_LANGUAGE LPWSTR - Biz language rule for the task
AZ_PROP_TASK_BIZRULE_IMPORTED_PATH LPWSTR - Path Bizrule was imported from
AZ_PROP_TASK_OPERATIONS AZ_STRING_ARRAY - Operations granted by this task
AZ_PROP_TASK_TASKS AZ_STRING_ARRAY - tasks granted by this task
AZ_PROP_TASK_IS_ROLE_DEFINITION PULONG - TRUE if this task is a role template
Return Value:
Status of the operation
--*/
{
DWORD WinStatus = NO_ERROR;
PAZP_TASK Task = (PAZP_TASK) GenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedShared( &AzGlResource ) );
//
// Return any object specific attribute
//
switch ( PropertyId ) {
//
// Return BizRule to the caller
//
case AZ_PROP_TASK_BIZRULE:
//
// check if bizrule should be returned
//
if ( Task->BizRule.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
} else {
*PropertyValue = AzpGetStringProperty( &Task->BizRule );
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
}
break;
//
// Return BizRule language to the caller
//
case AZ_PROP_TASK_BIZRULE_LANGUAGE:
//
// check if bizrule should be returned
//
if ( Task->BizRuleLanguage.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
} else {
*PropertyValue = AzpGetStringProperty( &Task->BizRuleLanguage );
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
}
break;
//
// Return BizRule imported path to the caller
//
case AZ_PROP_TASK_BIZRULE_IMPORTED_PATH:
//
// check if bizrule should be returned
//
if ( Task->BizRuleImportedPath.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
} else {
*PropertyValue = AzpGetStringProperty( &Task->BizRuleImportedPath );
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
}
break;
//
// Return the set of operations to the caller
//
case AZ_PROP_TASK_OPERATIONS:
if ( Flags & AZP_FLAGS_BY_GUID )
{
*PropertyValue = ObGetPropertyItemGuids( &Task->Operations);
}
else
{
*PropertyValue = ObGetPropertyItems( &Task->Operations);
}
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
break;
//
// Return the set of tasks to the caller
//
case AZ_PROP_TASK_TASKS:
if ( Flags & AZP_FLAGS_BY_GUID )
{
*PropertyValue = ObGetPropertyItemGuids( &Task->Tasks);
}
else
{
*PropertyValue = ObGetPropertyItems( &Task->Tasks);
}
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
break;
case AZ_PROP_TASK_IS_ROLE_DEFINITION:
*PropertyValue = AzpGetUlongProperty( (Task->IsRoleDefinition) ? 1 : 0 );
if ( *PropertyValue == NULL ) {
WinStatus = ERROR_NOT_ENOUGH_MEMORY;
}
break;
default:
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: invalid prop id %ld\n", PropertyId ));
WinStatus = ERROR_INVALID_PARAMETER;
break;
}
return WinStatus;
}
DWORD
AzpTaskSetProperty(
IN PGENERIC_OBJECT GenericObject,
IN ULONG Flags,
IN ULONG PropertyId,
IN PVOID PropertyValue
)
/*++
Routine Description:
This routine is the Task 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
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_TASK_BIZRULE LPWSTR - Biz rule for the task
AZ_PROP_TASK_BIZRULE_LANGUAGE LPWSTR - Biz language rule for the task
AZ_PROP_TASK_BIZRULE_IMPORTED_PATH LPWSTR - Path Bizrule was imported from
AZ_PROP_TASK_IS_ROLE_DEFINITION PULONG - TRUE if this task is a role template
Return Value:
Status of the operation
--*/
{
DWORD WinStatus = NO_ERROR;
PAZP_TASK Task = (PAZP_TASK) GenericObject;
AZP_STRING CapturedString;
AZP_STRING ValidValue1;
AZP_STRING ValidValue2;
BOOL bHasChanged = TRUE;
//
// Initialization
//
UNREFERENCED_PARAMETER( Flags );
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
AzpInitString( &CapturedString, NULL );
//
// Set any object specific attribute
//
switch ( PropertyId ) {
//
// Set BizRule on the object
//
case AZ_PROP_TASK_BIZRULE:
BEGIN_SETPROP( &WinStatus, Task, Flags, AZ_DIRTY_TASK_BIZRULE ) {
//
// Capture the input string
//
WinStatus = AzpCaptureString( &CapturedString,
(LPWSTR) PropertyValue,
CHECK_STRING_LENGTH( Flags, AZ_MAX_TASK_BIZRULE_LENGTH),
TRUE ); // NULL is OK
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
if (IsNormalFlags(Flags) && CapturedString.String != NULL)
{
//
// This SetProperty comes from the client. We will check against
// space only biz rules
//
BOOL bSpaceOnly = TRUE;
for (UINT i = 0; i < CapturedString.StringSize / sizeof(WCHAR) - 1; i++)
{
if (!iswspace(CapturedString.String[i]))
{
bSpaceOnly = FALSE;
break;
}
}
if (bSpaceOnly)
{
WinStatus = ERROR_INVALID_DATA;
goto Cleanup;
}
}
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
//
// check if bizrule attribute is allowed
//
if ( CapturedString.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
goto Cleanup;
}
//
// Ensure the language is set
//
if ( CapturedString.String != NULL &&
Task->BizRuleLanguage.String == NULL ) {
AzPrint(( AZD_INVPARM, "AzpTaskSetProperty: Must set language before bizrule\n" ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
} END_VALIDITY_CHECKING;
//
// Only process the change if the strings have changed
//
bHasChanged = !AzpEqualStrings( &CapturedString, &Task->BizRule );
if ( bHasChanged ) {
//
// Swap the old/new names
//
SafeEnterCriticalSection( &Task->RunningScriptCritSect );
AzpSwapStrings( &CapturedString, &Task->BizRule );
Task->BizRuleSerialNumber ++;
SafeLeaveCriticalSection( &Task->RunningScriptCritSect );
//
// Tell the script engine cache that the script has changed
//
AzpFlushBizRule( Task );
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
//
// Ensure the script is syntactically valid
//
if ( Task->BizRule.String != NULL &&
Task->BizRuleLanguage.String != NULL ) {
WinStatus = AzpParseBizRule( Task );
if ( WinStatus != NO_ERROR ) {
// Put the script back
SafeEnterCriticalSection( &Task->RunningScriptCritSect );
AzpSwapStrings( &CapturedString, &Task->BizRule );
Task->BizRuleSerialNumber ++;
SafeLeaveCriticalSection( &Task->RunningScriptCritSect );
}
}
} END_VALIDITY_CHECKING;
}
} END_SETPROP (bHasChanged);
break;
//
// Set BizRule language on the object
//
case AZ_PROP_TASK_BIZRULE_LANGUAGE:
BEGIN_SETPROP( &WinStatus, Task, Flags, AZ_DIRTY_TASK_BIZRULE_LANGUAGE ) {
//
// Capture the input string
//
WinStatus = AzpCaptureString( &CapturedString,
(LPWSTR) PropertyValue,
CHECK_STRING_LENGTH( Flags, AZ_MAX_TASK_BIZRULE_LANGUAGE_LENGTH),
TRUE ); // NULL is OK
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Ensure it is one of the valid values
//
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
//
// check if bizrule attribute is allowed
//
if ( CapturedString.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
goto Cleanup;
}
if ( CapturedString.String != NULL ) {
AzpInitString( &ValidValue1, L"VBScript" );
AzpInitString( &ValidValue2, L"JScript" );
if ( !AzpEqualStrings( &CapturedString, &ValidValue1) &&
!AzpEqualStrings( &CapturedString, &ValidValue2) ) {
AzPrint(( AZD_INVPARM, "AzpTaskSetProperty: invalid language %ws\n", CapturedString.String ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
}
} END_VALIDITY_CHECKING;
//
// Only process the change if the strings have changed
//
bHasChanged = !AzpEqualStrings( &CapturedString, &Task->BizRuleLanguage );
if ( bHasChanged ) {
//
// Swap the old/new names
//
SafeEnterCriticalSection( &Task->RunningScriptCritSect );
AzpSwapStrings( &CapturedString, &Task->BizRuleLanguage );
RtlZeroMemory( &Task->BizRuleLanguageClsid, sizeof(Task->BizRuleLanguageClsid) );
Task->BizRuleSerialNumber ++;
SafeLeaveCriticalSection( &Task->RunningScriptCritSect );
//
// Tell the script engine cache that the script has changed
//
AzpFlushBizRule( Task );
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
//
// Ensure the script is syntactically valid
//
if ( Task->BizRule.String != NULL &&
Task->BizRuleLanguage.String != NULL ) {
WinStatus = AzpParseBizRule( Task );
if ( WinStatus != NO_ERROR ) {
// Put the script back
SafeEnterCriticalSection( &Task->RunningScriptCritSect );
AzpSwapStrings( &CapturedString, &Task->BizRuleLanguage );
Task->BizRuleSerialNumber ++;
RtlZeroMemory( &Task->BizRuleLanguageClsid, sizeof(Task->BizRuleLanguageClsid) );
SafeLeaveCriticalSection( &Task->RunningScriptCritSect );
}
}
} END_VALIDITY_CHECKING;
}
} END_SETPROP (bHasChanged);
break;
//
// Set BizRule imported path on the object
//
case AZ_PROP_TASK_BIZRULE_IMPORTED_PATH:
BEGIN_SETPROP( &WinStatus, Task, Flags, AZ_DIRTY_TASK_BIZRULE_IMPORTED_PATH ) {
//
// Capture the input string
//
WinStatus = AzpCaptureString( &CapturedString,
(LPWSTR) PropertyValue,
CHECK_STRING_LENGTH( Flags, AZ_MAX_TASK_BIZRULE_IMPORTED_PATH_LENGTH),
TRUE ); // NULL is OK
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Ensure it is one of the valid values
//
//
// Do parameter validity checking
//
BEGIN_VALIDITY_CHECKING( Flags ) {
//
// check if bizrule attribute is allowed
//
if ( CapturedString.String != NULL &&
(ParentOfChild(GenericObject))->ObjectType == OBJECT_TYPE_SCOPE &&
(ParentOfChild(GenericObject))->PolicyAdmins.GenericObjects.UsedCount != 0 ) {
//
// the parent scope object is delegated, do not allow bizrule
//
AzPrint(( AZD_INVPARM, "AzTaskGetProperty: scope is delegated - bizrule not allowed %ld\n", PropertyId ));
WinStatus = ERROR_NOT_SUPPORTED;
goto Cleanup;
}
} END_VALIDITY_CHECKING;
//
// Swap the old/new names
//
AzpSwapStrings( &CapturedString, &Task->BizRuleImportedPath );
} END_SETPROP(bHasChanged);
break;
case AZ_PROP_TASK_IS_ROLE_DEFINITION:
BEGIN_SETPROP( &WinStatus, Task, Flags, AZ_DIRTY_TASK_IS_ROLE_DEFINITION ) {
WinStatus = AzpCaptureLong( PropertyValue, &Task->IsRoleDefinition );
} END_SETPROP(bHasChanged);
break;
default:
AzPrint(( AZD_INVPARM, "AzpTaskSetProperty: invalid prop id %ld\n", PropertyId ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Free any local resources
//
Cleanup:
AzpFreeString( &CapturedString );
return WinStatus;
}
DWORD
AzpTaskCheckRefLoop(
IN PAZP_TASK ParentTask,
IN PAZP_TASK CurrentTask,
IN ULONG GenericObjectListOffset
)
/*++
Routine Description:
This routine determines whether the task members of "CurrentTask"
reference "ParentTask". This is done to detect loops where the
task references itself directly or indirectly.
On entry, AzGlResource must be locked shared.
Arguments:
ParentTask - Task that contains the original membership.
CurrentTask - Task that is currently being inspected to see if it
loops back to ParentTask
GenericObjectListOffset - Offset to the particular GenericObjectList being
checked.
Return Value:
Status of the operation
ERROR_DS_LOOP_DETECT - A loop has been detected.
--*/
{
ULONG WinStatus;
PGENERIC_OBJECT_LIST GenericObjectList;
ULONG i;
PAZP_TASK NextTask;
//
// Check for a reference to ourself
//
ASSERT( AzpIsLockedShared( &AzGlResource ) );
if ( ParentTask == CurrentTask ) {
return ERROR_DS_LOOP_DETECT;
}
//
// Compute a pointer to the membership list to check
//
GenericObjectList = (PGENERIC_OBJECT_LIST)
(((LPBYTE)CurrentTask)+GenericObjectListOffset);
//
// Check all tasks that are members of the current task
//
for ( i=0; i<GenericObjectList->GenericObjects.UsedCount; i++ ) {
NextTask = (PAZP_TASK) (GenericObjectList->GenericObjects.Array[i]);
//
// Recursively check this task
//
WinStatus = AzpTaskCheckRefLoop( ParentTask, NextTask, GenericObjectListOffset );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
}
return NO_ERROR;
}
DWORD
AzpTaskAddPropertyItem(
IN PGENERIC_OBJECT GenericObject,
IN PGENERIC_OBJECT_LIST GenericObjectList,
IN PGENERIC_OBJECT LinkedToObject
)
/*++
Routine Description:
This routine is the task object specific worker routine for AzAddPropertyItem.
It does any object specific property adds
On entry, AzGlResource must be locked exclusive.
Arguments:
GenericObject - Specifies a pointer to the object to be modified
GenericObjectList - Specifies the object list the object is to be added to
LinkedToObject - Specifies the object that is being linked to
Return Value:
Status of the operation
--*/
{
DWORD WinStatus;
PAZP_TASK Task = (PAZP_TASK) GenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// If we're linking to a task,
// Ensure this newly added membership doesn't cause a task membership loop
//
if ( LinkedToObject->ObjectType == OBJECT_TYPE_TASK ) {
WinStatus = AzpTaskCheckRefLoop( Task,
(PAZP_TASK)LinkedToObject,
(ULONG)(((LPBYTE)GenericObjectList)-((LPBYTE)Task)) );
} else {
WinStatus = NO_ERROR;
}
//
// Free any local resources
//
return WinStatus;
}
DWORD
AzpTaskGetGenericChildHead(
IN AZ_HANDLE ParentHandle,
OUT PULONG ObjectType,
OUT PGENERIC_OBJECT_HEAD *GenericChildHead
)
/*++
Routine Description:
This routine determines whether ParentHandle supports Task objects as
children.
Arguments:
ParentHandle - Specifies a handle to the object that is the parent of the role.
This may be an Application Handle or a Scope handle.
ObjectType - Returns the object type of the ParentHandle.
GenericChildHead - Returns a pointer to the head of the list of roles objects
that are children of the object specified by ParentHandle. This in an unverified
pointer. The pointer is only valid after ParentHandle has been validated.
Return Value:
Status of the operation.
--*/
{
DWORD WinStatus;
//
// Determine the type of the parent handle
//
WinStatus = ObGetHandleType( (PGENERIC_OBJECT)ParentHandle,
FALSE, // ignore deleted objects
ObjectType );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
//
// Verify that the specified handle support children roles.
//
switch ( *ObjectType ) {
case OBJECT_TYPE_APPLICATION:
*GenericChildHead = &(((PAZP_APPLICATION)ParentHandle)->Tasks);
break;
case OBJECT_TYPE_SCOPE:
*GenericChildHead = &(((PAZP_SCOPE)ParentHandle)->Tasks);
break;
default:
return ERROR_INVALID_HANDLE;
}
return NO_ERROR;
}
DWORD
WINAPI
AzTaskCreate(
IN AZ_HANDLE ParentHandle,
IN LPCWSTR TaskName,
IN DWORD Reserved,
OUT PAZ_HANDLE TaskHandle
)
/*++
Routine Description:
This routine adds a task into the scope of the specified parent object
Arguments:
ParentHandle - Specifies a handle to the object that is the parent of the task.
This may be an Application Handle or a Scope handle.
TaskName - Specifies the name of the task to add.
Reserved - Reserved. Must by zero.
TaskHandle - Return a handle to the task.
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
--*/
{
DWORD WinStatus;
DWORD ObjectType;
PGENERIC_OBJECT_HEAD GenericChildHead;
//
// Determine that the parent handle supports tasks as children
//
WinStatus = AzpTaskGetGenericChildHead( ParentHandle,
&ObjectType,
&GenericChildHead );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
//
// Call the common routine to do most of the work
//
return ObCommonCreateObject(
(PGENERIC_OBJECT) ParentHandle,
ObjectType,
GenericChildHead,
OBJECT_TYPE_TASK,
TaskName,
Reserved,
(PGENERIC_OBJECT *) TaskHandle );
}
DWORD
WINAPI
AzTaskOpen(
IN AZ_HANDLE ParentHandle,
IN LPCWSTR TaskName,
IN DWORD Reserved,
OUT PAZ_HANDLE TaskHandle
)
/*++
Routine Description:
This routine opens a task into the scope of the specified parent object.
Arguments:
ParentHandle - Specifies a handle to the object that is the parent of the task.
This may be an Application Handle or a Scope handle.
TaskName - Specifies the name of the task to open
Reserved - Reserved. Must by zero.
TaskHandle - Return a handle to the task.
The caller must close this handle by calling AzCloseHandle.
Return Value:
NO_ERROR - The operation was successful
ERROR_NOT_FOUND - There is no task by that name
--*/
{
DWORD WinStatus;
DWORD ObjectType;
PGENERIC_OBJECT_HEAD GenericChildHead;
//
// Determine that the parent handle supports tasks as children
//
WinStatus = AzpTaskGetGenericChildHead( ParentHandle,
&ObjectType,
&GenericChildHead );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
//
// Call the common routine to do most of the work
//
return ObCommonOpenObject(
(PGENERIC_OBJECT) ParentHandle,
ObjectType,
GenericChildHead,
OBJECT_TYPE_TASK,
TaskName,
Reserved,
(PGENERIC_OBJECT *) TaskHandle );
}
DWORD
WINAPI
AzTaskEnum(
IN AZ_HANDLE ParentHandle,
IN DWORD Reserved,
IN OUT PULONG EnumerationContext,
OUT PAZ_HANDLE TaskHandle
)
/*++
Routine Description:
Enumerates all of the tasks for the specified parent object.
Arguments:
ParentHandle - Specifies a handle to the object that is the parent of the task.
This may be an Application Handle or a Scope handle.
Reserved - Reserved. Must by zero.
EnumerationContext - Specifies a context indicating the next task 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.
TaskHandle - Returns a handle to the next task 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
--*/
{
DWORD WinStatus;
DWORD ObjectType;
PGENERIC_OBJECT_HEAD GenericChildHead;
//
// Determine that the parent handle supports tasks as children
//
WinStatus = AzpTaskGetGenericChildHead( ParentHandle,
&ObjectType,
&GenericChildHead );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
//
// Call the common routine to do most of the work
//
return ObCommonEnumObjects(
(PGENERIC_OBJECT) ParentHandle,
ObjectType,
GenericChildHead,
EnumerationContext,
Reserved,
(PGENERIC_OBJECT *) TaskHandle );
}
DWORD
WINAPI
AzTaskDelete(
IN AZ_HANDLE ParentHandle,
IN LPCWSTR TaskName,
IN DWORD Reserved
)
/*++
Routine Description:
This routine deletes a task from the scope of the specified parent object.
Also deletes any child objects of TaskName.
Arguments:
ParentHandle - Specifies a handle to the object that is the parent of the task.
This may be an Application Handle or a Scope handle.
TaskName - Specifies the name of the task 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
--*/
{
DWORD WinStatus;
DWORD ObjectType;
PGENERIC_OBJECT_HEAD GenericChildHead;
//
// Determine that the parent handle supports tasks as children
//
WinStatus = AzpTaskGetGenericChildHead( ParentHandle,
&ObjectType,
&GenericChildHead );
if ( WinStatus != NO_ERROR ) {
return WinStatus;
}
//
// Call the common routine to do most of the work
//
return ObCommonDeleteObject(
(PGENERIC_OBJECT) ParentHandle,
ObjectType,
GenericChildHead,
OBJECT_TYPE_TASK,
TaskName,
Reserved );
}