windows-nt/Source/XPSP1/NT/base/fs/rdr2/rxce/midatlas.c

809 lines
23 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++ BUILD Version: 0009 // Increment this if a change has global effects
Copyright (c) 1987-1993 Microsoft Corporation
Module Name:
midatlas.c
Abstract:
This module defines the data structure used in mapping MIDS to the corresponding requests/
contexts associated with them.
Author:
Balan Sethu Raman (SethuR) 26-Aug-95 Created
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#include "midatlsp.h"
VOID
RxInitializeMidMapFreeList (
struct _MID_MAP_ *pMidMap
);
VOID
RxUninitializeMidMap (
struct _MID_MAP_ *pMidMap,
PCONTEXT_DESTRUCTOR pContextDestructor
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxInitializeMidMapFreeList)
#pragma alloc_text(PAGE, RxCreateMidAtlas)
#pragma alloc_text(PAGE, RxUninitializeMidMap)
#pragma alloc_text(PAGE, RxDestroyMidAtlas)
#endif
#define ENTRY_TYPE_FREE_MID_LIST (0x1)
#define ENTRY_TYPE_VALID_CONTEXT (0x2)
#define ENTRY_TYPE_MID_MAP (0x3)
#define ENTRY_TYPE_MASK (0x3)
#define MID_MAP_FLAGS_CAN_BE_EXPANDED (0x1)
#define MID_MAP_FLAGS_FREE_POOL (0x2)
//INLINE ULONG _GetEntryType(PVOID pEntry)
#define _GetEntryType(pEntry) \
((ULONG)((ULONG_PTR)(pEntry)) & ENTRY_TYPE_MASK)
//INLINE PVOID _GetEntryPointer(PVOID pEntry)
#define _GetEntryPointer(pEntry) \
((PVOID)((ULONG_PTR)(pEntry) & ~ENTRY_TYPE_MASK))
#define _MakeEntry(pContext,EntryType) \
(PVOID)((ULONG_PTR)(pContext) | (EntryType))
//INLINE PMID_MAP _GetFirstMidMap()
/*++
Routine Description:
This first MID_MAP instance in the list
Return Value:
a valid PMID_MAP, NULL if none exists.
Notes:
This routine assumes that the necessary concurrency control action has been taken
--*/
#define _GetFirstMidMap(pListHead) \
(IsListEmpty(pListHead) \
? NULL \
: (PMID_MAP) \
(CONTAINING_RECORD((pListHead)->Flink, \
MID_MAP, \
MidMapList)))
//INLINE PSMBCEDB_SERVER_ENTRY GetNextMidMap(PLIST_ENTRY pListHead, PMID_MAP pMidMap)
/*++
Routine Description:
This routine returns the next MID_MAP in the list
Arguments:
pListHead - the list of MID_MAP's
pMidMap - the current instance
Return Value:
a valid PMID_MAP, NULL if none exists.
Notes:
This routine assumes that the necessary concurrency control action has been taken
--*/
#define _GetNextMidMap(pListHead,pMidMap) \
(((pMidMap)->MidMapList.Flink == pListHead) \
? NULL \
: (PMID_MAP) \
(CONTAINING_RECORD((pMidMap)->MidMapList.Flink, \
MID_MAP, \
MidMapList)))
//INLINE VOID _AddMidMap(
// PLIST_ENTRY pListHead,
// PMID_MAP pMidMap)
/*++
Routine Description:
This routine adds a MID_MAP instance to a list
Arguments:
pListHead - the list of MID_MAP's
pMidMap - the MID_MAP to be added
--*/
#define _AddMidMap(pListHead,pMidMap) \
{ \
PMID_MAP pPredecessor; \
pPredecessor = _GetFirstMidMap(pListHead); \
while (pPredecessor != NULL) { \
if (pPredecessor->Level < pMidMap->Level) { \
pPredecessor = _GetNextMidMap(pListHead,pPredecessor); \
} else { \
pPredecessor = (PMID_MAP) \
CONTAINING_RECORD( \
pPredecessor->MidMapList.Blink, \
MID_MAP, \
MidMapList); \
break; \
} \
} \
\
if (pPredecessor == NULL) { \
InsertTailList(pListHead,&((pMidMap)->MidMapList)); \
} else { \
(pMidMap)->MidMapList.Flink = pPredecessor->MidMapList.Flink; \
pPredecessor->MidMapList.Flink = &(pMidMap)->MidMapList; \
\
(pMidMap)->MidMapList.Blink = &pPredecessor->MidMapList; \
(pMidMap)->MidMapList.Flink->Blink = &(pMidMap)->MidMapList; \
} \
}
//INLINE VOID _RemoveMidMap(PMID_MAP pMidMap)
/*++
Routine Description:
This routine removes a MID_MAP instance from the list
Arguments:
pMidMap - the MID_MAP instance to be removed
--*/
#define _RemoveMidMap(pMidMap) \
RemoveEntryList(&(pMidMap)->MidMapList)
VOID
RxInitializeMidMapFreeList(PMID_MAP pMidMap)
/*++
Routine Description:
This routine initializes a MID_MAP data structure.
Arguments:
pMidMap - the MID_MAP instance to be initialized.
Notes:
--*/
{
USHORT i;
PVOID *pEntryValue = (PVOID *)&pMidMap->Entries[1];
PVOID *pEntriesPointer = (PVOID *)&pMidMap->Entries;
PAGED_CODE();
//DbgPrint("RxInitializeMidMapFreeList .. Entry\n");
if (pMidMap->MaximumNumberOfMids > 0) {
pMidMap->pFreeMidListHead = pMidMap->Entries;
for (i = 1; i <= pMidMap->MaximumNumberOfMids - 1;i++,pEntryValue++) {
*pEntriesPointer++ = _MakeEntry(pEntryValue,ENTRY_TYPE_FREE_MID_LIST);
}
*pEntriesPointer = _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST);
}
//DbgPrint("RxInitializeMidMapFreeList .. Exit\n");
}
PRX_MID_ATLAS
RxCreateMidAtlas(
USHORT MaximumNumberOfMids,
USHORT MidsAllocatedAtStart)
/*++
Routine Description:
This routine allocates a new instance of MID_ATLAS data structure.
Arguments:
MaximumNumberOfMids - the maximum number of MIDS in the atlas.
MidsAllocatedAtStart - the number of MIDS allocated at start
Notes:
--*/
{
PRX_MID_ATLAS pMidAtlas;
PMID_MAP pMidMap;
ULONG AtlasSize;
USHORT MidsAllocatedRoundedToPowerOf2;
USHORT MaximumMidsRoundedToPowerOf2;
UCHAR MidFieldWidth,MaximumMidFieldWidth;
PAGED_CODE();
// Round off the Mids allocated at Start to a power of two
MaximumMidsRoundedToPowerOf2 = 0x100;
MaximumMidFieldWidth = 8;
if (MaximumMidsRoundedToPowerOf2 != MaximumNumberOfMids) {
if (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
while (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
MaximumMidFieldWidth++;
}
} else {
while (MaximumNumberOfMids < MaximumMidsRoundedToPowerOf2) {
MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> 1;
MaximumMidFieldWidth--;
}
MaximumMidFieldWidth++;
MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
}
}
MidsAllocatedRoundedToPowerOf2 = 0x100;
MidFieldWidth = 8;
if (MidsAllocatedRoundedToPowerOf2 != MidsAllocatedAtStart) {
if (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
while (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
MidFieldWidth++;
}
} else {
while (MidsAllocatedAtStart < MidsAllocatedRoundedToPowerOf2) {
MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 >> 1;
MidFieldWidth--;
}
MidFieldWidth++;
MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
}
}
AtlasSize = sizeof(RX_MID_ATLAS) +
FIELD_OFFSET(MID_MAP,Entries);
if (MaximumNumberOfMids == MidsAllocatedAtStart) {
AtlasSize += (sizeof(PVOID) * MidsAllocatedAtStart);
} else {
AtlasSize += (sizeof(PVOID) * MidsAllocatedRoundedToPowerOf2);
}
pMidAtlas = (PRX_MID_ATLAS)RxAllocatePoolWithTag(
NonPagedPool,
AtlasSize,
RXCE_MIDATLAS_POOLTAG);
if (pMidAtlas != NULL) {
pMidMap = (PMID_MAP)(pMidAtlas + 1);
pMidMap->Flags = 0;
pMidAtlas->MaximumNumberOfMids = MaximumNumberOfMids;
pMidAtlas->MidsAllocated = MidsAllocatedAtStart;
pMidAtlas->NumberOfMidsInUse = 0;
pMidAtlas->NumberOfMidsDiscarded = 0;
pMidAtlas->MaximumMidFieldWidth = MaximumMidFieldWidth;
pMidMap->MaximumNumberOfMids = MidsAllocatedAtStart;
pMidMap->NumberOfMidsInUse = 0;
pMidMap->BaseMid = 0;
pMidMap->IndexMask = MidsAllocatedRoundedToPowerOf2 - 1;
pMidMap->IndexAlignmentCount = 0;
pMidMap->IndexFieldWidth = MidFieldWidth;
pMidMap->Level = 1;
InitializeListHead(&pMidAtlas->MidMapFreeList);
InitializeListHead(&pMidAtlas->MidMapExpansionList);
RxInitializeMidMapFreeList(pMidMap);
_AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
pMidAtlas->pRootMidMap = pMidMap;
if (MaximumNumberOfMids > MidsAllocatedAtStart) {
// Round off the maximum number of MIDS to determine the level and the
// size of the quantum ( allocation increments)
pMidMap->Flags |= MID_MAP_FLAGS_CAN_BE_EXPANDED;
pMidAtlas->MidQuantum = 32;
pMidAtlas->MidQuantumFieldWidth = 5;
MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> (pMidMap->IndexAlignmentCount + 5);
if (MaximumMidsRoundedToPowerOf2 > 0) {
pMidAtlas->NumberOfLevels = 3;
} else {
pMidAtlas->NumberOfLevels = 2;
}
} else {
pMidAtlas->MidQuantum = 0;
pMidAtlas->NumberOfLevels = 1;
pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
}
}
//DbgPrint("RxAllocatMidAtlas .. Exit (pMidAtlas) %lx\n",pMidAtlas);
return pMidAtlas;
}
VOID
RxUninitializeMidMap(
PMID_MAP pMidMap,
PCONTEXT_DESTRUCTOR pContextDestructor)
/*++
Routine Description:
This routine uninitializes a MID_MAP data structure.
Arguments:
pMidMap -- the MID_MAP instance to be uninitialized.
pContextDestructor -- the context destructor
Notes:
--*/
{
USHORT i;
ULONG EntryType;
PAGED_CODE();
//DbgPrint("RxUninitializeMidMap .. Entry No.Of MIDS in Use %ld\n",pMidMap->NumberOfMidsInUse);
RxLog(("_UninitMidMap .. num= %ld\n",pMidMap->NumberOfMidsInUse));
RxWmiLog(LOG,
RxUninitializeMidMap,
LOGXSHORT(pMidMap->NumberOfMidsInUse));
for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
PMID_MAP pChildMidMap;
EntryType = _GetEntryType(pMidMap->Entries[i]);
switch (EntryType) {
case ENTRY_TYPE_MID_MAP :
{
pChildMidMap = (PMID_MAP)_GetEntryPointer(pMidMap->Entries[i]);
RxUninitializeMidMap(pChildMidMap,pContextDestructor);
}
break;
case ENTRY_TYPE_VALID_CONTEXT :
{
if (pContextDestructor != NULL) {
PVOID pContext;
pContext = _GetEntryPointer(pMidMap->Entries[i]);
(pContextDestructor)(pContext);
}
}
break;
default:
break;
}
}
if (pMidMap->Flags & MID_MAP_FLAGS_FREE_POOL) {
RxFreePool(pMidMap);
}
//DbgPrint("RxUninitializeMidMap .. Exit\n");
}
VOID
RxDestroyMidAtlas(
PRX_MID_ATLAS pMidAtlas,
PCONTEXT_DESTRUCTOR pContextDestructor)
/*++
Routine Description:
This routine frees a MID_ATLAS instance. As a side effect it invokes the
passed in context destructor on every valid context in the MID_ATLAS
Arguments:
pMidAtlas - the MID_ATLAS instance to be freed.
PCONTEXT_DESTRUCTOR - the associated context destructor
Notes:
--*/
{
PAGED_CODE();
//DbgPrint("RxFreeMidAtlas .. Entry\n");
RxUninitializeMidMap(pMidAtlas->pRootMidMap,pContextDestructor);
RxFreePool(pMidAtlas);
//DbgPrint("RxFreeMidAtlas .. Exit\n");
}
PVOID
RxMapMidToContext(
PRX_MID_ATLAS pMidAtlas,
USHORT Mid)
/*++
Routine Description:
This routine maps a MID to its associated context in a MID_ATLAS.
Arguments:
pMidAtlas - the MID_ATLAS instance.
Mid - the MId to be mapped
Return value:
the associated context, NULL if none exists
Notes:
--*/
{
ULONG EntryType;
PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
PVOID pContext;
ULONG Index;
//DbgPrint("RxMapMidToContext Mid %lx ",Mid);
for (;;) {
Index = (Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount;
if( Index >= pMidMap->MaximumNumberOfMids ) {
pContext = NULL;
break;
}
pContext = pMidMap->Entries[Index];
EntryType = _GetEntryType(pContext);
pContext = (PVOID)_GetEntryPointer(pContext);
if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
break;
} else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
pContext = NULL;
break;
} else if (EntryType == ENTRY_TYPE_MID_MAP) {
pMidMap = (PMID_MAP)pContext;
} else {
pContext = NULL;
break;
}
}
//DbgPrint("Context %lx \n",pContext);
return pContext;
}
NTSTATUS
RxMapAndDissociateMidFromContext(
PRX_MID_ATLAS pMidAtlas,
USHORT Mid,
PVOID *pContextPointer)
/*++
Routine Description:
This routine maps a MID to its associated context in a MID_ATLAS.
Arguments:
pMidAtlas - the MID_ATLAS instance.
Mid - the MId to be mapped
Return value:
the associated context, NULL if none exists
Notes:
--*/
{
ULONG EntryType;
PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
PVOID pContext;
PVOID *pEntry;
//DbgPrint("RxMapAndDissociateMidFromContext Mid %lx ",Mid);
for (;;) {
pEntry = &pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
pContext = *pEntry;
EntryType = _GetEntryType(pContext);
pContext = (PVOID)_GetEntryPointer(pContext);
if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
pMidMap->NumberOfMidsInUse--;
if (pMidMap->pFreeMidListHead == NULL) {
_RemoveMidMap(pMidMap);
_AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
}
*pEntry = _MakeEntry(pMidMap->pFreeMidListHead,ENTRY_TYPE_FREE_MID_LIST);
pMidMap->pFreeMidListHead = pEntry;
break;
} else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
pContext = NULL;
break;
} else if (EntryType == ENTRY_TYPE_MID_MAP) {
pMidMap = (PMID_MAP)pContext;
}
}
pMidAtlas->NumberOfMidsInUse--;
//DbgPrint("Context %lx\n",pContext);
*pContextPointer = pContext;
return STATUS_SUCCESS;
}
NTSTATUS
RxReassociateMid(
PRX_MID_ATLAS pMidAtlas,
USHORT Mid,
PVOID pNewContext)
/*++
Routine Description:
This routine maps a MID to its associated context in a MID_ATLAS.
Arguments:
pMidAtlas - the MID_ATLAS instance.
Mid - the MId to be mapped
pNewContext - the new context
Return value:
the associated context, NULL if none exists
Notes:
--*/
{
ULONG EntryType;
PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
PVOID pContext;
//DbgPrint("RxReassociateMid Mid %lx ",Mid);
for (;;) {
pContext = pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
EntryType = _GetEntryType(pContext);
pContext = (PVOID)_GetEntryPointer(pContext);
if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount]
= _MakeEntry(pNewContext,ENTRY_TYPE_VALID_CONTEXT);
break;
} else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
ASSERT(!"Valid MID Atlas");
break;
} else if (EntryType == ENTRY_TYPE_MID_MAP) {
pMidMap = (PMID_MAP)pContext;
}
}
//DbgPrint("New COntext %lx\n",pNewContext);
return STATUS_SUCCESS;
}
NTSTATUS
RxAssociateContextWithMid(
PRX_MID_ATLAS pMidAtlas,
PVOID pContext,
PUSHORT pNewMid)
/*++
Routine Description:
This routine initializes a MID_MAP data structure.
Arguments:
pMidMap - the MID_MAP instance to be initialized.
Return Value:
STATUS_SUCCESS if successful, otherwise one of the following errors
STATUS_INSUFFICIENT_RESOURCES
STATUS_UNSUCCESSFUL -- no mid could be associated
Notes:
--*/
{
NTSTATUS Status;
PMID_MAP pMidMap;
PVOID *pContextPointer;
//DbgPrint("RxAssociateContextWithMid Context %lx ",pContext);
// Scan the list of MID_MAP's which have free entries in them.
if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapFreeList)) != NULL) {
ASSERT(pMidMap->pFreeMidListHead != _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST));
pMidMap->NumberOfMidsInUse++;
pContextPointer = pMidMap->pFreeMidListHead;
pMidMap->pFreeMidListHead = _GetEntryPointer(*(pMidMap->pFreeMidListHead));
*pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
*pNewMid = ((USHORT)
(pContextPointer - (PVOID *)&pMidMap->Entries)
<< pMidMap->IndexAlignmentCount) |
pMidMap->BaseMid;
// Check if the MID_MAP needs to be removed from the list of MID_MAP's with
// free entries
if (pMidMap->pFreeMidListHead == NULL) {
_RemoveMidMap(pMidMap);
// Check if it can be added to the expansion list.
if (pMidAtlas->NumberOfLevels > pMidMap->Level) {
_AddMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
}
}
Status = STATUS_SUCCESS;
} else if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList)) != NULL) {
PMID_MAP pNewMidMap;
USHORT i;
ULONG NewMidMapSize;
// Locate the index in the mid map for the new mid map
pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList);
while (pMidMap != NULL) {
for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
if (_GetEntryType(pMidMap->Entries[i]) != ENTRY_TYPE_MID_MAP) {
break;
}
}
if (i < pMidMap->MaximumNumberOfMids) {
break;
} else {
pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
_RemoveMidMap(pMidMap);
pMidMap = _GetNextMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
}
}
if (pMidMap != NULL) {
USHORT NumberOfEntriesInMap = pMidAtlas->MaximumNumberOfMids -
pMidAtlas->NumberOfMidsInUse;
if (NumberOfEntriesInMap > pMidAtlas->MidQuantum) {
NumberOfEntriesInMap = pMidAtlas->MidQuantum;
}
else if( NumberOfEntriesInMap == 1 )
{
// The MID_MAP design does not allow for maps of length 1. Extend to 2
NumberOfEntriesInMap++;
}
if (NumberOfEntriesInMap > 0) {
NewMidMapSize = FIELD_OFFSET(MID_MAP,Entries) +
NumberOfEntriesInMap * sizeof(PVOID);
pNewMidMap = (PMID_MAP)RxAllocatePoolWithTag(
NonPagedPool,
NewMidMapSize,
RXCE_MIDATLAS_POOLTAG);
if (pNewMidMap != NULL) {
pNewMidMap->Flags = MID_MAP_FLAGS_FREE_POOL;
pNewMidMap->MaximumNumberOfMids = NumberOfEntriesInMap;
pNewMidMap->NumberOfMidsInUse = 0;
pNewMidMap->BaseMid = (pMidMap->BaseMid |
i << pMidMap->IndexAlignmentCount);
pNewMidMap->IndexAlignmentCount = pMidMap->IndexAlignmentCount +
pMidMap->IndexFieldWidth;
pNewMidMap->IndexMask = (pMidAtlas->MidQuantum - 1) << pNewMidMap->IndexAlignmentCount;
pNewMidMap->IndexFieldWidth = pMidAtlas->MidQuantumFieldWidth;
RxInitializeMidMapFreeList(pNewMidMap);
//
// After the RxInitializeMidMapFreeList call above the
// pFreeMidListHead points to Entries[0]. We will be storing
// the value pMidMap->Entries[i] at this location so we need
// to make pFreeMidListHead point to Entries[1].
//
pNewMidMap->pFreeMidListHead = _GetEntryPointer(*(pNewMidMap->pFreeMidListHead));
//
// Set up the mid map appropriately.
//
pNewMidMap->NumberOfMidsInUse = 1;
pNewMidMap->Entries[0] = pMidMap->Entries[i];
pNewMidMap->Level = pMidMap->Level + 1;
//
// The new MinMap is stored at the pMidMap->Entries[i] location.
//
pMidMap->Entries[i] = _MakeEntry(pNewMidMap,ENTRY_TYPE_MID_MAP);
//
// Update the free list and the expansion list respectively.
//
_AddMidMap(&pMidAtlas->MidMapFreeList,pNewMidMap);
pNewMidMap->NumberOfMidsInUse++;
pContextPointer = pNewMidMap->pFreeMidListHead;
pNewMidMap->pFreeMidListHead = _GetEntryPointer(*(pNewMidMap->pFreeMidListHead));
*pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
*pNewMid = ((USHORT)
(pContextPointer - (PVOID *)&pNewMidMap->Entries)
<< pNewMidMap->IndexAlignmentCount) |
pNewMidMap->BaseMid;
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
if (Status == (STATUS_SUCCESS)) {
pMidAtlas->NumberOfMidsInUse++;
}
//DbgPrint("Mid %lx\n",*pNewMid);
return Status;
}