windows-nt/Source/XPSP1/NT/ds/security/azroles/adminmgr.cxx
2020-09-26 16:20:57 +08:00

700 lines
14 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
adminmgr.cxx
Abstract:
Routines implementing the Admin Manager object
Author:
Cliff Van Dyke (cliffv) 11-Apr-2001
--*/
#include "pch.hxx"
//
// Global Data
//
//
// Global list of all admin manager for this process
// Access serialized by AzGlResource
//
GENERIC_OBJECT_HEAD AzGlAdminManagers;
RTL_RESOURCE AzGlResource;
BOOL ResourceInitialized = FALSE;
GUID AzGlZeroGuid;
#if DBG
BOOL CritSectInitialized = FALSE;
#endif // DBG
BOOL
AzDllInitialize(VOID)
/*++
Routine Description
This initializes global events and variables for the DLL.
Arguments
none
Return Value
Boolean: TRUE on success, FALSE on fail.
--*/
{
BOOL RetVal = TRUE;
//
// Don't call back on thread start/stop
// ???
RtlZeroMemory( &AzGlZeroGuid, sizeof(AzGlZeroGuid) );
// Initialize the resource
//
__try {
RtlInitializeResource( &AzGlResource );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
RetVal = FALSE;
KdPrint(("AzRoles.dll: RtlInitializeResource failed: 0x%lx\n",
GetExceptionCode() ));
}
ResourceInitialized = TRUE;
//
// Initialize the root of the tree of objects
//
AzpLockResourceExclusive( &AzGlResource );
ObInitGenericHead( &AzGlAdminManagers, OBJECT_TYPE_ADMIN_MANAGER, NULL, NULL, NULL );
AzpUnlockResource( &AzGlResource );
//
// Initialize the stack allocator
//
SafeAllocaInitialize(
SAFEALLOCA_USE_DEFAULT,
SAFEALLOCA_USE_DEFAULT,
AzpAllocateHeap,
AzpFreeHeap
);
#if DBG
//
// Initialize the allocator
//
InitializeListHead ( &AzGlAllocatedBlocks );
__try {
InitializeCriticalSection ( &AzGlAllocatorCritSect );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
RetVal = FALSE;
KdPrint(("AzRoles.dll: InitializCriticalSection (AzGlAllocatorCritSect) failed: 0x%lx\n",
GetExceptionCode() ));
}
CritSectInitialized = TRUE;
#endif // DBG
#ifdef AZROLESDBG
//
// Initialize debugging
//
__try {
InitializeCriticalSection ( &AzGlLogFileCritSect );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
RetVal = FALSE;
KdPrint(("AzRoles.dll: InitializCriticalSection (AzGlLogFileCritSect) failed: 0x%lx\n",
GetExceptionCode() ));
}
// AzGlDbFlag = AZD_ALL;
AzGlDbFlag = AZD_INVPARM; // | AZD_PERSIST | AZD_PERSIST_MORE;
// AzGlLogFile = INVALID_HANDLE_VALUE;
#endif // AZROLESDBG
return RetVal;
}
BOOL
AzDllUnInitialize(VOID)
/*++
Routine Description
This uninitializes global events and variables for the DLL.
Arguments
none
Return Value
Boolean: TRUE on success, FALSE on fail.
--*/
{
BOOL RetVal = TRUE;
//
// Don't call back on thread start/stop
//
// Handle detaching from a process.
//
//
// Delete the resource
//
if ( ResourceInitialized ) {
RtlDeleteResource( &AzGlResource );
ResourceInitialized = FALSE;
}
#if DBG
//
// Done with the allocator
//
if ( CritSectInitialized ) {
ASSERT( IsListEmpty( &AzGlAllocatedBlocks ));
DeleteCriticalSection ( &AzGlAllocatorCritSect );
CritSectInitialized = FALSE;
}
#endif // DBG
return RetVal;
}
VOID
AzpUnload(
VOID
)
/*++
Routine Description
Force the DLL unload routine to execute
Arguments
NONE
Return Value
NONE
--*/
{
#if DBG // Don't check this in ???
AzDllUnInitialize();
ASSERT( IsListEmpty( &AzGlAllocatedBlocks ));
#endif // DBG
}
DWORD
AzpAdminManagerInit(
IN PGENERIC_OBJECT ParentGenericObject,
IN PGENERIC_OBJECT ChildGenericObject
)
/*++
Routine Description:
This routine is a worker routine for AzInitialize. 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_ADMIN_MANAGER AdminManager = (PAZP_ADMIN_MANAGER) ChildGenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Initialize the lists of child objects
// Let the generic object manager know all of the types of children we support
//
ASSERT( ParentGenericObject == NULL );
UNREFERENCED_PARAMETER( ParentGenericObject );
ChildGenericObject->ChildGenericObjectHead = &AdminManager->Applications;
// List of child applications
ObInitGenericHead( &AdminManager->Applications,
OBJECT_TYPE_APPLICATION,
ChildGenericObject,
&AdminManager->Groups,
NULL ); // Doesn't share namespace
// List of child groups
ObInitGenericHead( &AdminManager->Groups,
OBJECT_TYPE_GROUP,
ChildGenericObject,
&AdminManager->AzpSids,
NULL ); // Doesn't share namespace (YET)
// List of child AzpSids
ObInitGenericHead( &AdminManager->AzpSids,
OBJECT_TYPE_SID,
ChildGenericObject,
NULL,
NULL ); // Doesn't share namespace
return NO_ERROR;
}
VOID
AzpAdminManagerFree(
IN PGENERIC_OBJECT GenericObject
)
/*++
Routine Description:
This routine is a worker routine for AdminManager 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_ADMIN_MANAGER AdminManager = (PAZP_ADMIN_MANAGER) GenericObject;
//
// Initialization
//
ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
//
// Free any local strings
//
AzpFreeString( &AdminManager->PolicyUrl );
}
DWORD
WINAPI
AzInitialize(
IN DWORD StoreType,
IN LPCWSTR PolicyUrl,
IN DWORD Flags,
IN DWORD Reserved,
OUT PAZ_HANDLE AdminManagerHandle
)
/*++
Routine Description:
This routine initializes admin manager. This routine must be called before any other
routine.
Arguments:
StoreType - Takes one of the AZ_ADMIN_STORE_* defines
PolicyUrl - Specifies the location of the policy store
Flags - Specifies flags that control the behavior of AzInitialize
AZ_ADMIN_FLAG_CREATE: Create the policy database
Reserved - Reserved. Must by zero.
AdminManagerHandle - Return a handle to the AdminManager.
The caller must close this handle by calling AzCloseHandle.
Return Value:
NO_ERROR - The operation was successful
ERROR_ALREADY_EXISTS - AZ_ADMIN_FLAG_CREATE flag was specified and the policy already exists
ERROR_FILE_NOT_FOUND - AZ_ADMIN_FLAG_CREATE flag was not specified and the policy does not already exist
--*/
{
DWORD WinStatus;
PGENERIC_OBJECT AdminManager = NULL;
AZP_STRING AdminManagerName;
AZP_STRING CapturedString;
//
// Grab the global lock
//
AzpLockResourceExclusive( &AzGlResource );
AzpInitString( &AdminManagerName, NULL );
AzpInitString( &CapturedString, NULL );
//
// Initialization
//
__try {
*AdminManagerHandle = NULL;
} __except( EXCEPTION_EXECUTE_HANDLER ) {
WinStatus = RtlNtStatusToDosError( GetExceptionCode());
goto Cleanup;
}
//
// Validate the input parameters
//
if ( Reserved != 0 ) {
AzPrint(( AZD_INVPARM, "AzInitialize: Reserved != 0\n" ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
switch ( StoreType ) {
case AZ_ADMIN_STORE_SAMPLE:
break;
case AZ_ADMIN_STORE_UNKNOWN:
case AZ_ADMIN_STORE_AD:
case AZ_ADMIN_STORE_XML:
default:
AzPrint(( AZD_INVPARM, "AzInitialize: StoreType invalid %ld\n", StoreType ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if ( Flags & ~AZ_ADMIN_FLAG_VALID ) {
AzPrint(( AZD_INVPARM, "AzInitialize: Invalid flags 0x%lx\n", Flags ));
WinStatus = ERROR_INVALID_FLAGS;
goto Cleanup;
}
//
// Capture the Policy URL
//
WinStatus = AzpCaptureString( &CapturedString,
(LPWSTR) PolicyUrl,
AZ_MAX_POLICY_URL_LENGTH,
TRUE ); // NULL is OK
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Create the object
//
WinStatus = ObCreateObject(
NULL, // There is no parent object
&AzGlAdminManagers,
OBJECT_TYPE_ADMIN_MANAGER,
&AdminManagerName,
&AdminManager );
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Set admin manager specific fields
//
AzpSwapStrings( &CapturedString, &((PAZP_ADMIN_MANAGER)AdminManager)->PolicyUrl );
((PAZP_ADMIN_MANAGER)AdminManager)->StoreType = StoreType;
//
// Load the objects for the database store
//
WinStatus = AzpPersistOpen(
(PAZP_ADMIN_MANAGER)AdminManager,
(Flags & AZ_ADMIN_FLAG_CREATE) != 0 );
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Return the handle to the caller
//
ObIncrHandleRefCount( AdminManager );
*AdminManagerHandle = AdminManager;
WinStatus = NO_ERROR;
//
// Free locally used resources
//
Cleanup:
if ( AdminManager != NULL ) {
ObDereferenceObject( AdminManager );
}
AzpFreeString( &CapturedString );
//
// Drop the global lock
//
AzpUnlockResource( &AzGlResource );
return WinStatus;
}
DWORD
WINAPI
AzCloseHandle(
IN AZ_HANDLE AzHandle,
IN DWORD Reserved
)
/*++
Routine Description:
Close a handle returned from any of the Az* routines
Arguments:
AzHandle - Passes in the handle to be closed.
Reserved - Reserved. Must by zero.
Return Value:
NO_ERROR - The operation was successful.
ERROR_INVALID_HANDLE - The passed in handle was invalid
ERROR_SERVER_HAS_OPEN_HANDLES - That passed in handle is an AdminManager handle
and the caller open handles to child objects.
--*/
{
DWORD WinStatus;
PGENERIC_OBJECT ReferencedGenericObject = NULL;
PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT) AzHandle;
DWORD ObjectType;
//
// Grab the global lock
// Only for the admin manager case do we modify anything.
//
AzpLockResourceShared( &AzGlResource );
//
// Validate the input parameters
//
if ( Reserved != 0 ) {
AzPrint(( AZD_INVPARM, "AzCloseHandle: Reserved != 0\n" ));
WinStatus = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Determine the type of the object
//
WinStatus = ObGetHandleType( GenericObject,
TRUE, // Ok to close handle for deleted object
&ObjectType );
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
//
// Grab the lock exclusively if we're going to change the database
//
if ( ObjectType == OBJECT_TYPE_ADMIN_MANAGER ) {
AzpLockResourceSharedToExclusive( &AzGlResource );
}
//
// Validate the passed in handle
//
WinStatus = ObReferenceObjectByHandle( GenericObject,
TRUE, // Allow deleted objects
FALSE, // No need to refresh cache on a close
ObjectType );
if ( WinStatus != NO_ERROR ) {
goto Cleanup;
}
ReferencedGenericObject = GenericObject;
//
// Handle close of AdminManager handles
//
if ( ObjectType == OBJECT_TYPE_ADMIN_MANAGER ) {
PAZP_ADMIN_MANAGER AdminManager = (PAZP_ADMIN_MANAGER) GenericObject;
//
// Fail if there are any child handles open
// Otherwise we'll have dangling references
//
if ( AdminManager->TotalHandleReferenceCount != 1 ) {
WinStatus = ERROR_SERVER_HAS_OPEN_HANDLES;
goto Cleanup;
}
//
// Close the database store
//
AzpPersistClose( AdminManager );
//
// Remove the entry from the global list of AdminManagers
//
RemoveEntryList( &GenericObject->Next );
// One from ObReferenceObjectByHandle,
// one for being in the global list,
// one because the handle itself isn't closed yet.
ASSERT( GenericObject->ReferenceCount == 3 );
// No longer in the global list
ObDereferenceObject( GenericObject );
}
//
// Actually close the handle
//
ObDecrHandleRefCount( GenericObject );
//
// ??? This is really an overactive assert. Yank it once someone complains.
ASSERT( (GenericObject->Flags & GENOBJ_FLAGS_DIRTY) == 0 );
WinStatus = NO_ERROR;
//
// Free locally used resources
//
Cleanup:
if ( ReferencedGenericObject != NULL ) {
ObDereferenceObject( ReferencedGenericObject );
}
//
// Drop the global lock
//
AzpUnlockResource( &AzGlResource );
return WinStatus;
}
VOID
WINAPI
AzFreeMemory(
IN PVOID Buffer
)
/*++
Routine Description
Free memory returned from AzXXXGetProperty
Arguments
Buffer - address of buffer to free
Return Value
None
--*/
{
if ( Buffer != NULL ) {
AzpFreeHeap( Buffer );
}
}