700 lines
14 KiB
C++
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 );
|
||
|
}
|
||
|
}
|