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.
1057 lines
29 KiB
1057 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
genobj.h
|
|
|
|
Abstract:
|
|
|
|
Definitions for the generic object implementation.
|
|
|
|
AZ roles has so many objects that need creation, enumeration, etc
|
|
that it seems prudent to have a single body of code for doing those operations.
|
|
|
|
|
|
Author:
|
|
|
|
Cliff Van Dyke (cliffv) 11-Apr-2001
|
|
|
|
--*/
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Structure definitions
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// A generic object list head.
|
|
//
|
|
// This structure represent the head of a linked list of objects. The linked
|
|
// list of objects are considered to be "children" of this structure.
|
|
//
|
|
|
|
typedef struct _GENERIC_OBJECT_HEAD {
|
|
|
|
//
|
|
// Head of the linked list of objects
|
|
//
|
|
|
|
LIST_ENTRY Head;
|
|
|
|
//
|
|
// Count of entries on the list headed by Head
|
|
//
|
|
|
|
ULONG ObjectCount;
|
|
|
|
//
|
|
// Tree of the names of the objects
|
|
//
|
|
|
|
RTL_GENERIC_TABLE AvlTree;
|
|
|
|
//
|
|
// Back pointer to the GenericObject containing this structure
|
|
//
|
|
|
|
struct _GENERIC_OBJECT *ParentGenericObject;
|
|
|
|
|
|
//
|
|
// Each of the list heads that are rooted on a single object are linked
|
|
// together. That list is headed by GENERIC_OBJECT->ChildGenericObjectHead.
|
|
// This field is a pointer to the next entry in the list.
|
|
//
|
|
|
|
struct _GENERIC_OBJECT_HEAD *SiblingGenericObjectHead;
|
|
|
|
//
|
|
// The next sequence number to give out.
|
|
//
|
|
|
|
ULONG NextSequenceNumber;
|
|
|
|
//
|
|
// Object type of objects in this list
|
|
//
|
|
|
|
ULONG ObjectType;
|
|
|
|
//
|
|
// Flag to indicate that the parent needs to be loaded before this object can be
|
|
// referenced
|
|
//
|
|
|
|
BOOLEAN LoadParentBeforeReferencing;
|
|
|
|
//
|
|
// The order of the defines below must match the tables at the top of genobj.cxx
|
|
//
|
|
// Define object types that are not visible to the providers
|
|
//
|
|
#define OBJECT_TYPE_SID (OBJECT_TYPE_COUNT)
|
|
#define OBJECT_TYPE_CLIENT_CONTEXT (OBJECT_TYPE_COUNT+1)
|
|
#define OBJECT_TYPE_ROOT (OBJECT_TYPE_COUNT+2)
|
|
#define OBJECT_TYPE_MAXIMUM (OBJECT_TYPE_COUNT+3)
|
|
|
|
|
|
} GENERIC_OBJECT_HEAD, *PGENERIC_OBJECT_HEAD;
|
|
|
|
//
|
|
// The name of a generic object
|
|
//
|
|
// This is a separate structure since the AVL tree manager insists on allocating its own
|
|
// structure. Combine that with the facts that objects can be renamed and that a pointer
|
|
// to the object is returned directly to the user as the handle to the object. These
|
|
// facts imply that the structure containing the object name and the structure implementing
|
|
// the "handle" cannot be the same structure. I chose to not implement a separate "handle"
|
|
// structure. Such an implementation would have to "re-create and copy" the generic object
|
|
// structure upon rename.
|
|
//
|
|
|
|
typedef struct _GENERIC_OBJECT_NAME {
|
|
|
|
//
|
|
// Name of the object
|
|
//
|
|
AZP_STRING ObjectName;
|
|
|
|
//
|
|
// Pointer to the GenericObject structure named by this name
|
|
//
|
|
struct _GENERIC_OBJECT *GenericObject;
|
|
|
|
} GENERIC_OBJECT_NAME, *PGENERIC_OBJECT_NAME;
|
|
|
|
//
|
|
// The new name of a generic object
|
|
//
|
|
// This structure is only used during an AzPersistUpdateCache. Every attempt is made
|
|
// to update the name of the object in the AVL tree. However, if there are name conflicts,
|
|
// a GUID-ized name is used. That's certainly OK in a pinch. And we'll leave the name
|
|
// that way if we can't fix it or in certain bounday low memory conditions. However, we
|
|
// should fix it up if we can. This structure remembers the real name of the object and
|
|
// allows AzpPersistReconcile to try to fix the name up.
|
|
//
|
|
|
|
typedef struct _NEW_OBJECT_NAME {
|
|
|
|
//
|
|
// Link to the next new name for the same authorization store object
|
|
//
|
|
|
|
LIST_ENTRY Next;
|
|
|
|
//
|
|
// Pointer to the GenericObject structure named by this name
|
|
// The specified generic object has its reference count incremented.
|
|
//
|
|
struct _GENERIC_OBJECT *GenericObject;
|
|
|
|
//
|
|
// New name of the object
|
|
//
|
|
AZP_STRING ObjectName;
|
|
|
|
} NEW_OBJECT_NAME, *PNEW_OBJECT_NAME;
|
|
|
|
//
|
|
// Object List
|
|
//
|
|
// Some objects have lists of references to other objects. These lists are
|
|
// not parent/child relationships. Rather they represent memberships, etc.
|
|
//
|
|
// This structure represents the head of such a list.
|
|
//
|
|
// Both the pointed-from and pointed-to object have a generic object list. The
|
|
// "forward" link represents the list that is managed via external API. The
|
|
// "backward" link is provided to allow fixup of references when an object is deleted.
|
|
// The "backward" link is also provided for cases where internal routines need to
|
|
// traverse the link relationship in the opposite direction of the external API.
|
|
// By convention, GENERIC_OBJECT_LIST instances in the forward direction are named
|
|
// simply by the name of the object to point to. For instance, an object list that points
|
|
// to AZ_OPERATION objects might be called "Operations". By convention, GENERIC_OBJECT_LIST
|
|
// instances in the backward direction are prefixed by the name "back". For instance,
|
|
// "backTasks".
|
|
//
|
|
// Note, there really isn't any reason why we couldn't expose "AddPropertyItem" and
|
|
// "RemovePropertyItem" APIs for the "back" lists. See the IsBackLink and LinkPairId
|
|
// definition.
|
|
//
|
|
|
|
typedef struct _GENERIC_OBJECT_LIST {
|
|
|
|
//
|
|
// Each of the object lists that are rooted on a single object are linked
|
|
// together. That list is headed by GENERIC_OBJECT->GenericObjectLists.
|
|
// This field is a pointer to the next entry in the list.
|
|
//
|
|
|
|
struct _GENERIC_OBJECT_LIST *NextGenericObjectList;
|
|
|
|
//
|
|
// Since an object list is a list of other objects, we want to be able to
|
|
// generically find the other objects. The array below is an array of pointers
|
|
// to the head of the lists that contain the other objects.
|
|
//
|
|
//
|
|
// Unused elements in this array are set to NULL.
|
|
//
|
|
// These pointers are always pointers to a field in a "parent" structure.
|
|
// Therefore, reference counts aren't needed. Instead, the "child" structure
|
|
// containing the pointer to the parent will be deleted before the parent structure.
|
|
//
|
|
|
|
#define GEN_OBJECT_HEAD_COUNT 3
|
|
PGENERIC_OBJECT_HEAD GenericObjectHeads[GEN_OBJECT_HEAD_COUNT];
|
|
|
|
//
|
|
// List identifier.
|
|
//
|
|
// The code maintains the link and the backlink. To do that, the code needs to
|
|
// find one the "other" generic object list from this one. That algorithm uses
|
|
// the IsBackLink and LinkPairId field.
|
|
//
|
|
// One object list has IsBackLink set TRUE and the other set FALSE. This handles
|
|
// the case where an object contain both a forward an backward object list. For
|
|
// instance, the AZ_GROUP object contains the AppMembers and backAppMembers fields.
|
|
// This field differentiates between the two.
|
|
//
|
|
// There are cases where an object has multiple links between the same object types.
|
|
// For instance, the AZ_GROUP object has both AppMembers and AppNonMembers links.
|
|
// In those cases, the LinkPairId is set to a unique value to identify the pair.
|
|
// In most cases, the value is simply zero.
|
|
//
|
|
BOOL IsBackLink;
|
|
ULONG LinkPairId;
|
|
|
|
#define AZP_LINKPAIR_MEMBERS 1
|
|
#define AZP_LINKPAIR_NON_MEMBERS 2
|
|
#define AZP_LINKPAIR_SID_MEMBERS 3
|
|
#define AZP_LINKPAIR_SID_NON_MEMBERS 4
|
|
#define AZP_LINKPAIR_POLICY_ADMINS 5
|
|
#define AZP_LINKPAIR_POLICY_READERS 6
|
|
#define AZP_LINKPAIR_DELEGATED_POLICY_USERS 7
|
|
|
|
//
|
|
// Dirty Bit to be set when this list is changed
|
|
//
|
|
|
|
ULONG DirtyBit;
|
|
|
|
|
|
//
|
|
// The array of pointers to the generic objects.
|
|
//
|
|
// Being in this list does not increment the ReferenceCount on the pointed-to
|
|
// generic object.
|
|
//
|
|
|
|
AZP_PTR_ARRAY GenericObjects;
|
|
|
|
//
|
|
// An array of pointers to AZP_DELTA_ENTRY containing the GUIDs of the pointed to objects.
|
|
//
|
|
// This array contains GUIDs of links that have not yet been persisted.
|
|
// It also contains GUIDs of links that have been updated from the persistence
|
|
// provider but not yet merged into GenericObjects.
|
|
|
|
AZP_PTR_ARRAY DeltaArray;
|
|
|
|
} GENERIC_OBJECT_LIST, *PGENERIC_OBJECT_LIST;
|
|
|
|
//
|
|
// A generic object
|
|
//
|
|
|
|
typedef struct _GENERIC_OBJECT {
|
|
|
|
//
|
|
// Link to the next instance of an object of this type for the same parent object
|
|
//
|
|
|
|
LIST_ENTRY Next;
|
|
|
|
//
|
|
// Back pointer to the head of the list this object is in
|
|
//
|
|
|
|
PGENERIC_OBJECT_HEAD ParentGenericObjectHead;
|
|
|
|
GENERIC_OBJECT_HEAD AzpSids;
|
|
|
|
//
|
|
// Pointer to the list heads for children of this object
|
|
// This is a static list of the various GENERIC_OBJECT_HEAD structures
|
|
// that exist in the object type specific portion of this object.
|
|
// The list allows the generic object code to have insight into the
|
|
// children of this object.
|
|
//
|
|
|
|
PGENERIC_OBJECT_HEAD ChildGenericObjectHead;
|
|
|
|
//
|
|
// Pointer to the list heads of pointers to other objects
|
|
// This is a static list of the various GENERIC_OBJECT_LIST structures
|
|
// that exist in the object type specific portion of this object.
|
|
// The list allows the generic object code to have insight into the
|
|
// other types of objects pointed to by this object.
|
|
//
|
|
|
|
struct _GENERIC_OBJECT_LIST *GenericObjectLists;
|
|
|
|
//
|
|
// Pointer to the generic object at the root of all generic objects
|
|
// (Pointer to an AzAuthorizationStore object)
|
|
//
|
|
|
|
struct _AZP_AZSTORE *AzStoreObject;
|
|
|
|
//
|
|
// Pointer to provider specific data for this object
|
|
//
|
|
|
|
PVOID ProviderData;
|
|
|
|
//
|
|
// A list of SIDs as policy users
|
|
// Used by AzAuthorizationStore, AzApplication and AzScope objects
|
|
//
|
|
|
|
GENERIC_OBJECT_LIST PolicyAdmins;
|
|
GENERIC_OBJECT_LIST PolicyReaders;
|
|
|
|
//
|
|
// Boolean specifying whether or not the object ACL-able
|
|
//
|
|
// Used by AzAuthorizationStore, AzApplication and AzScope objects
|
|
|
|
LONG IsAclSupported;
|
|
|
|
//
|
|
// Boolean specifying if delegation is supported. It is set during the
|
|
// persist open calls at the provider levels. For example, an XML provider
|
|
// would set this to FALSE, while an LDAP provider would set it to TRUE
|
|
//
|
|
// Used by AzAuthorizationStore and AzApplication objects
|
|
//
|
|
|
|
LONG IsDelegationSupported;
|
|
|
|
//
|
|
// A list of SIDs as delegated users
|
|
// Used by AzAuthorizationStore and AzApplication
|
|
//
|
|
|
|
GENERIC_OBJECT_LIST DelegatedPolicyUsers;
|
|
|
|
//
|
|
// Name of the object
|
|
//
|
|
|
|
PGENERIC_OBJECT_NAME ObjectName;
|
|
|
|
|
|
//
|
|
// Opaque private information added by an application
|
|
//
|
|
|
|
AZP_STRING ApplicationData;
|
|
|
|
|
|
//
|
|
// Description of the object
|
|
//
|
|
|
|
AZP_STRING Description;
|
|
|
|
//
|
|
// Boolean indicating if the caller can write the object
|
|
//
|
|
|
|
LONG IsWritable;
|
|
|
|
//
|
|
// Boolen indicating if the caller can create children for this object
|
|
//
|
|
|
|
LONG CanCreateChildren;
|
|
|
|
//
|
|
// GUID of the object
|
|
// The Guid of the object is assigned by the persistence provider.
|
|
// The GUID is needed to make the object rename safe.
|
|
//
|
|
|
|
GUID PersistenceGuid;
|
|
|
|
|
|
//
|
|
// Number of references to this instance of the object
|
|
// These are references from within our code.
|
|
//
|
|
|
|
LONG ReferenceCount;
|
|
|
|
//
|
|
// Number of references to this instance of the object
|
|
// These are references represented by handles passed back to our caller.
|
|
//
|
|
|
|
LONG HandleReferenceCount;
|
|
|
|
//
|
|
// Sequence number of this object.
|
|
// The list specified in Next is maintained in SequenceNumber order.
|
|
// New entries are added to the tail end.
|
|
// Enumerations are returned in SequenceNumber order.
|
|
// SequenceNumber is returned to the caller as the EnumerationContext.
|
|
//
|
|
// This mechanism allows insertions and deletions to be handled seemlessly.
|
|
//
|
|
|
|
ULONG SequenceNumber;
|
|
|
|
//
|
|
// Specific object type represented by this generic object
|
|
//
|
|
|
|
ULONG ObjectType;
|
|
|
|
//
|
|
// Flags describing attributes of the generic object
|
|
//
|
|
|
|
ULONG Flags;
|
|
|
|
#define GENOBJ_FLAGS_DELETED 0x01 // Object has been deleted
|
|
#define GENOBJ_FLAGS_PERSIST_OK 0x02 // Persist provider has finished with this object
|
|
#define GENOBJ_FLAGS_REFRESH_ME 0x04 // Object needs to be refreshed from cache
|
|
|
|
//
|
|
// Flags to indicate which attributes are dirty
|
|
// High order bits are generic to all objects
|
|
// Low order bits are specific to individual objects
|
|
//
|
|
// Bits in "DirtyBits" indicates that the object needs to be submitted
|
|
// See the AZ_DIRTY_* defines.
|
|
//
|
|
|
|
ULONG DirtyBits;
|
|
|
|
//
|
|
// Flags to indicate that Persistence provider has changed the attribute
|
|
// Access to this field is serialized by the PersistCritSect
|
|
//
|
|
// See the AZ_DIRTY_* defines.
|
|
//
|
|
|
|
ULONG PersistDirtyBits;
|
|
|
|
//
|
|
// Boolean specifying whether or not audits should be generated. Only
|
|
// Authorizartion Store and application objects have this property. When this
|
|
// is set to TRUE all possible audits for this AzAuthStore/application are generated.
|
|
//
|
|
|
|
LONG IsGeneratingAudits;
|
|
|
|
//
|
|
// Apply SACL property. Only AzAuthorizationStore, application and Scope objects
|
|
// have this property.
|
|
//
|
|
|
|
LONG ApplySacl;
|
|
|
|
//
|
|
// whether apply SACL property is supported or not.
|
|
// For AD stores, AzAuthorizationStore, application and Scope objects support it.
|
|
// For XML stores, only AzAuthorizationStore supports it.
|
|
//
|
|
|
|
LONG IsSACLSupported;
|
|
|
|
//
|
|
// Boolean to indicate if the children are loaded into cache
|
|
//
|
|
|
|
BOOLEAN AreChildrenLoaded;
|
|
|
|
//
|
|
// Boolean to indicate that the object has been closed
|
|
//
|
|
|
|
BOOLEAN ObjectClosed;
|
|
|
|
} GENERIC_OBJECT, *PGENERIC_OBJECT;
|
|
|
|
//
|
|
// Property ID to dirty bit mapping table
|
|
//
|
|
// This structure gives a mapping between property ID and the corresponding dirty bit.
|
|
// It also provides a default value for the property.
|
|
//
|
|
|
|
typedef struct _AZP_DEFAULT_VALUE {
|
|
|
|
ULONG PropertyId;
|
|
|
|
ULONG DirtyBit;
|
|
|
|
PVOID DefaultValue;
|
|
|
|
} AZP_DEFAULT_VALUE, *PAZP_DEFAULT_VALUE;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Macro definitions
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Macro to determine if a GENERIC_OBJECT_LIST is a list of sids
|
|
//
|
|
|
|
#define AzpIsSidList( _gol ) \
|
|
((_gol)->GenericObjectHeads[0] != NULL && \
|
|
(_gol)->GenericObjectHeads[0]->ObjectType == OBJECT_TYPE_SID )
|
|
|
|
//
|
|
// Macro to determine the address of a parent object from a child object
|
|
//
|
|
|
|
#define ParentOfChild( _go ) \
|
|
((_go)->ParentGenericObjectHead->ParentGenericObject)
|
|
|
|
//
|
|
// Macro to determine if an object type is a container type object or not
|
|
//
|
|
|
|
#define IsContainerObject( _objT ) \
|
|
( (_objT) == OBJECT_TYPE_AZAUTHSTORE || \
|
|
(_objT) == OBJECT_TYPE_APPLICATION || \
|
|
(_objT) == OBJECT_TYPE_SCOPE )
|
|
|
|
//
|
|
// Macro to determine is an object type is a delegator type object or not
|
|
//
|
|
|
|
#define IsDelegatorObject( _objT ) \
|
|
( (_objT) == OBJECT_TYPE_AZAUTHSTORE || \
|
|
(_objT) == OBJECT_TYPE_APPLICATION )
|
|
|
|
//
|
|
// Macros to determine if the provider actually supports ACLs or delegation
|
|
//
|
|
|
|
#define CHECK_ACL_SUPPORT(_o) \
|
|
(IsContainerObject( (_o)->ObjectType ) ? \
|
|
((_o)->IsAclSupported ? NO_ERROR : ERROR_NOT_SUPPORTED) : \
|
|
ERROR_INVALID_PARAMETER )
|
|
|
|
#define CHECK_DELEGATION_SUPPORT(_o) \
|
|
(IsDelegatorObject( (_o)->ObjectType ) ? \
|
|
((_o)->IsDelegationSupported ? NO_ERROR : ERROR_NOT_SUPPORTED) : \
|
|
ERROR_INVALID_PARAMETER )
|
|
|
|
//
|
|
// Macro to set a property in the cache.
|
|
//
|
|
// This macro acts as a wrapper around the code to set the property.
|
|
// The macro detects the mode of the caller and properly handles the following:
|
|
//
|
|
// * Ensures object supports this "dirty" bit
|
|
// * Sets the appropriate "dirty" bit depending on mode
|
|
// * Avoids setting the property on AzUpdateCache if the property is dirty
|
|
//
|
|
// The correct calling sequence of the macros is:
|
|
//
|
|
// case AZ_PROP_XXX:
|
|
// BEGIN_SETPROP( &WinStatus, Object, AZ_DIRTY_XXX ) {
|
|
// WinStatus = f( Object->Property );
|
|
// /* Optionally */ if ( WinStatus != NO_ERROR ) goto Cleanup
|
|
// } END_SETPROP;
|
|
// break;
|
|
//
|
|
|
|
extern DWORD AzGlObjectAllDirtyBits[];
|
|
|
|
#define BEGIN_SETPROP( __WinStatusPtr, __ObjectPtr, __Flags, __DirtyBit ) \
|
|
{ \
|
|
DWORD *_WinStatusPtr = (__WinStatusPtr); \
|
|
PGENERIC_OBJECT _GenericObject = ((PGENERIC_OBJECT)(__ObjectPtr)); \
|
|
ULONG _DirtyBit = (__DirtyBit); \
|
|
ULONG _Flags = (__Flags); \
|
|
BOOLEAN _DoSetProperty = FALSE; \
|
|
\
|
|
if ( (AzGlObjectAllDirtyBits[_GenericObject->ObjectType] & _DirtyBit) == 0 ) { \
|
|
AzPrint(( AZD_INVPARM, "SetProperty: Object doesn't support dirty bit 0x%lx\n", _DirtyBit )); \
|
|
*_WinStatusPtr = ERROR_INVALID_PARAMETER; \
|
|
\
|
|
} else if ( IsNormalFlags(_Flags) ) { \
|
|
\
|
|
_DoSetProperty = TRUE; \
|
|
AzPrint(( AZD_PERSIST_MORE, "IsNormalFlags(_Flags) = TRUE\n" )); \
|
|
if ( (_Flags & AZP_FLAGS_SETTING_TO_DEFAULT) == 0 && !AzpAzStoreVersionAllowWrite(_GenericObject->AzStoreObject) ) \
|
|
{ \
|
|
*_WinStatusPtr = ERROR_REVISION_MISMATCH; \
|
|
} \
|
|
else { \
|
|
_DoSetProperty = TRUE; \
|
|
} \
|
|
\
|
|
} else { \
|
|
\
|
|
if ( (_GenericObject->DirtyBits & _DirtyBit) == 0 ) { \
|
|
AzPrint(( AZD_PERSIST_MORE, "(_GenericObject->DirtyBits & _DirtyBit) = 0\n" )); \
|
|
_DoSetProperty = TRUE; \
|
|
} else if (IsRefreshFlags(_Flags)) { \
|
|
AzPrint(( AZD_PERSIST_MORE, "IsRefreshFlags(_Flags) = TRUE\n" )); \
|
|
_DoSetProperty = TRUE; \
|
|
} else { \
|
|
*_WinStatusPtr = NO_ERROR; \
|
|
} \
|
|
\
|
|
} \
|
|
\
|
|
if ( _DoSetProperty ) { \
|
|
|
|
#define END_SETPROP( __PropHasChanged ) \
|
|
if ( *_WinStatusPtr == NO_ERROR && \
|
|
(_Flags & AZP_FLAGS_SETTING_TO_DEFAULT) == 0 ) { \
|
|
if ( IsNormalFlags( _Flags ) ) { \
|
|
if ( (__PropHasChanged) ) { \
|
|
_GenericObject->DirtyBits |= _DirtyBit; \
|
|
} \
|
|
} else { \
|
|
ASSERT( AzpIsCritsectLocked( &_GenericObject->AzStoreObject->PersistCritSect ) ); \
|
|
ASSERT( (_GenericObject->Flags & GENOBJ_FLAGS_PERSIST_OK) == 0 ); \
|
|
_GenericObject->PersistDirtyBits |= _DirtyBit; \
|
|
} \
|
|
\
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Macro to do validity checking after setting a property in the cache.
|
|
//
|
|
// This macro acts as a wrapper around the code to do the validity checking.
|
|
// Some validity checking is only appropriate only when the caller is the UI
|
|
// or application. This validity checking may not be valid when setting default
|
|
// values or when populating the cache from the store.
|
|
//
|
|
// The correct calling sequence of the macros is:
|
|
//
|
|
// case AZ_PROP_XXX:
|
|
// BEGIN_SETPROP( &WinStatus, Object, AZ_DIRTY_XXX ) {
|
|
//
|
|
// BEGIN_VALIDITY_CHECKING( Flags ) {
|
|
// checks to see if property is valid
|
|
// } END_VALIDITY_CHECKING;
|
|
//
|
|
// WinStatus = f( Object->Property );
|
|
//
|
|
// /* Optionally */ if ( WinStatus != NO_ERROR ) goto Cleanup
|
|
// } END_SETPROP;
|
|
// break;
|
|
//
|
|
|
|
#define DO_VALIDITY_CHECKING( _Flags ) \
|
|
( IsNormalFlags(_Flags) && (_Flags & (AZP_FLAGS_SETTING_TO_DEFAULT)) == 0 )
|
|
|
|
#define BEGIN_VALIDITY_CHECKING( _Flags ) \
|
|
{ \
|
|
\
|
|
if ( DO_VALIDITY_CHECKING( _Flags ) ) {
|
|
|
|
#define END_VALIDITY_CHECKING \
|
|
} \
|
|
}
|
|
|
|
//
|
|
// Macro to handle validity check on string length.
|
|
//
|
|
// The correct calling sequence of the macros is:
|
|
//
|
|
// case AZ_PROP_XXX:
|
|
// BEGIN_SETPROP( &WinStatus, Object, AZ_DIRTY_XXX ) {
|
|
//
|
|
// //
|
|
// // Capture the input string
|
|
// //
|
|
//
|
|
// WinStatus = AzpCaptureString( &CapturedString,
|
|
// (LPWSTR) PropertyValue,
|
|
// CHECK_STRING_LENGTH( Flags, AZ_MAX_XXX),
|
|
// TRUE ); // NULL is OK
|
|
//
|
|
// if ( WinStatus != NO_ERROR ) {
|
|
// goto Cleanup;
|
|
// }
|
|
//
|
|
// WinStatus = f( Object->Property );
|
|
//
|
|
// /* Optionally */ if ( WinStatus != NO_ERROR ) goto Cleanup
|
|
// } END_SETPROP;
|
|
// break;
|
|
//
|
|
|
|
#define CHECK_STRING_LENGTH( _Flags, _MaxLen ) \
|
|
(DO_VALIDITY_CHECKING( _Flags ) ? (_MaxLen) : 0xFFFFFFFF)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Procedure definitions
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
ObInitGenericHead(
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead,
|
|
IN ULONG ObjectType,
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN PGENERIC_OBJECT_HEAD SiblingGenericObjectHead OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
ObFreeGenericObject(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
VOID
|
|
ObIncrHandleRefCount(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObDecrHandleRefCount(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObGetHandleType(
|
|
IN PGENERIC_OBJECT Handle,
|
|
IN BOOL AllowDeletedObjects,
|
|
OUT PULONG ObjectType
|
|
);
|
|
|
|
DWORD
|
|
ObReferenceObjectByName(
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead,
|
|
IN PAZP_STRING ObjectName,
|
|
IN ULONG Flags,
|
|
OUT PGENERIC_OBJECT *RetGenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObReferenceObjectByHandle(
|
|
IN PGENERIC_OBJECT Handle,
|
|
IN BOOL AllowDeletedObjects,
|
|
IN BOOLEAN RefreshCache,
|
|
IN ULONG ObjectType
|
|
);
|
|
|
|
VOID
|
|
ObDereferenceObject(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
typedef DWORD
|
|
(OBJECT_INIT_ROUTINE)(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN PGENERIC_OBJECT ChildGenericObject
|
|
);
|
|
|
|
typedef DWORD
|
|
(OBJECT_NAME_CONFLICT_ROUTINE)(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN PAZP_STRING ChildObjectNameString
|
|
);
|
|
|
|
typedef VOID
|
|
(OBJECT_FREE_ROUTINE)(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
typedef DWORD
|
|
(OBJECT_GET_PROPERTY_ROUTINE)(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG Flags,
|
|
IN ULONG PropertyId,
|
|
OUT PVOID *PropertyValue
|
|
);
|
|
|
|
typedef DWORD
|
|
(OBJECT_SET_PROPERTY_ROUTINE)(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG Flags,
|
|
IN ULONG PropertyId,
|
|
IN PVOID PropertyValue
|
|
);
|
|
|
|
typedef DWORD
|
|
(OBJECT_ADD_PROPERTY_ITEM_ROUTINE)(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN PGENERIC_OBJECT LinkedToObject
|
|
);
|
|
|
|
DWORD
|
|
ObCreateObject(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN ULONG ChildObjectType,
|
|
IN PAZP_STRING ChildObjectNameString,
|
|
IN GUID *ChildObjectGuid OPTIONAL,
|
|
IN ULONG Flags,
|
|
OUT PGENERIC_OBJECT *RetChildGenericObject
|
|
);
|
|
|
|
//
|
|
// Flags to various internal functions
|
|
// The low order 2 bytes of this DWORD are shared with the AZPE_FLAGS defines in azper.h
|
|
//
|
|
|
|
#define AZP_FLAGS_SETTING_TO_DEFAULT 0x00010000 // Property is being set to default value
|
|
#define AZP_FLAGS_BY_GUID 0x00020000 // Name based routine should use GUID instead
|
|
#define AZP_FLAGS_ALLOW_DELETED_OBJECTS 0x00040000 // Allow deleted objects to be found
|
|
#define AZP_FLAGS_REFRESH_CACHE 0x00080000 // Ensure cache is up to date
|
|
#define AZP_FLAGS_RECONCILE 0x00100000 // The caller is AzpPersistReconcile
|
|
|
|
//
|
|
// Macro to return TRUE if this is a normal caller
|
|
// (e.g., the app and not an internal caller)
|
|
//
|
|
#define IsNormalFlags( _Flags ) (((_Flags) & (AZPE_FLAGS_PERSIST_MASK|AZP_FLAGS_RECONCILE)) == 0 )
|
|
#define IsRefreshFlags( _Flags ) (((_Flags) & (AZPE_FLAGS_PERSIST_REFRESH)) != 0 )
|
|
|
|
DWORD
|
|
ObGetProperty(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG Flags,
|
|
IN ULONG PropertyId,
|
|
OUT PVOID *PropertyValue
|
|
);
|
|
|
|
DWORD
|
|
ObSetProperty(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG Flags,
|
|
IN ULONG PropertyId,
|
|
IN PVOID PropertyValue
|
|
);
|
|
|
|
DWORD
|
|
ObSetPropertyToDefault(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG DirtyBits
|
|
);
|
|
|
|
|
|
DWORD
|
|
ObCommonCreateObject(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN ULONG ParentObjectType,
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN ULONG ChildObjectType,
|
|
IN LPCWSTR ChildObjectName,
|
|
IN DWORD Reserved,
|
|
OUT PGENERIC_OBJECT *RetChildGenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObCommonOpenObject(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN ULONG ParentObjectType,
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN ULONG ChildObjectType,
|
|
IN LPCWSTR ChildObjectName,
|
|
IN DWORD Reserved,
|
|
OUT PGENERIC_OBJECT *RetChildGenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObEnumObjects(
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN BOOL EnumerateDeletedObjects,
|
|
IN BOOL RefreshCache,
|
|
IN OUT PULONG EnumerationContext,
|
|
OUT PGENERIC_OBJECT *RetChildGenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObCommonEnumObjects(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN ULONG ParentObjectType,
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN OUT PULONG EnumerationContext,
|
|
IN DWORD Reserved,
|
|
OUT PGENERIC_OBJECT *RetChildGenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObCommonGetProperty(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG Flags,
|
|
IN ULONG PropertyId,
|
|
IN DWORD Reserved,
|
|
OUT PVOID *PropertyValue
|
|
);
|
|
|
|
DWORD
|
|
ObCommonSetProperty(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG PropertyId,
|
|
IN DWORD Reserved,
|
|
IN PVOID PropertyValue
|
|
);
|
|
|
|
VOID
|
|
ObMarkObjectDeleted(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
DWORD
|
|
ObCommonDeleteObject(
|
|
IN PGENERIC_OBJECT ParentGenericObject,
|
|
IN ULONG ParentObjectType,
|
|
IN PGENERIC_OBJECT_HEAD GenericChildHead,
|
|
IN ULONG ChildObjectType,
|
|
IN LPCWSTR ChildObjectName,
|
|
IN DWORD Reserved
|
|
);
|
|
|
|
VOID
|
|
ObInitObjectList(
|
|
IN OUT PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN PGENERIC_OBJECT_LIST NextGenericObjectList OPTIONAL,
|
|
IN BOOL IsBackLink,
|
|
IN ULONG LinkPairId,
|
|
IN ULONG DirtyBit,
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead0 OPTIONAL,
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead1 OPTIONAL,
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead2 OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
ObAddPropertyItem(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN ULONG Flags,
|
|
IN PAZP_STRING ObjectName
|
|
);
|
|
|
|
DWORD
|
|
ObLookupPropertyItem(
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN PAZP_STRING ObjectName,
|
|
OUT PULONG InsertionPoint OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
ObRemovePropertyItem(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN PAZP_STRING ObjectName
|
|
);
|
|
|
|
PAZ_STRING_ARRAY
|
|
ObGetPropertyItems(
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList
|
|
);
|
|
|
|
PAZ_GUID_ARRAY
|
|
ObGetPropertyItemGuids(
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList
|
|
);
|
|
|
|
VOID
|
|
ObRemoveObjectListLink(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN PGENERIC_OBJECT_LIST GenericObjectList,
|
|
IN ULONG Index
|
|
);
|
|
|
|
VOID
|
|
ObRemoveObjectListLinks(
|
|
IN PGENERIC_OBJECT GenericObject
|
|
);
|
|
|
|
VOID
|
|
ObFreeObjectList(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN OUT PGENERIC_OBJECT_LIST GenericObjectList
|
|
);
|
|
|
|
DWORD
|
|
ObCheckNameConflict(
|
|
IN PGENERIC_OBJECT_HEAD GenericObjectHead,
|
|
IN PAZP_STRING ObjectNameString,
|
|
IN ULONG ConflictListOffset,
|
|
IN ULONG GrandchildListOffset,
|
|
IN ULONG GrandChildConflictListOffset
|
|
);
|
|
|
|
DWORD
|
|
ObMapPropIdToObjectList(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN ULONG PropertyId,
|
|
OUT PGENERIC_OBJECT_LIST *GenericObjectList,
|
|
OUT PULONG ObjectType
|
|
);
|
|
|
|
BOOLEAN
|
|
ObLookupDelta(
|
|
IN ULONG DeltaFlags,
|
|
IN GUID *Guid,
|
|
IN PAZP_PTR_ARRAY AzpPtrArray,
|
|
OUT PULONG InsertionPoint OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
ObAddDeltaToArray(
|
|
IN ULONG DeltaFlags,
|
|
IN GUID *Guid,
|
|
IN PAZP_PTR_ARRAY AzpPtrArray,
|
|
IN BOOLEAN DiscardDeletes
|
|
);
|
|
|
|
VOID
|
|
ObFreeDeltaArray(
|
|
IN PAZP_PTR_ARRAY DeltaArray,
|
|
IN BOOLEAN FreeAllEntries
|
|
);
|
|
|
|
BOOLEAN
|
|
ObAllocateNewName(
|
|
IN PGENERIC_OBJECT GenericObject,
|
|
IN PAZP_STRING ObjectName
|
|
);
|
|
|
|
VOID
|
|
ObFreeNewName(
|
|
IN PNEW_OBJECT_NAME NewObjectName
|
|
);
|
|
|
|
DWORD
|
|
ObUnloadChildGenericHeads(
|
|
IN PGENERIC_OBJECT pParentObject
|
|
);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|