//================================================================================ // Copyright (C) 1997 Microsoft Corporation // Author: RameshV // Description: implements the basic structures for bitmasks // ThreadSafe: no // Locks: none // Please read stdinfo.txt for programming style. //================================================================================ #include #include #include "bitmask.h" DWORD _inline MemBit1Init( OUT PM_BITMASK1 *Bits, IN DWORD nBits ) { PM_BITMASK1 Bits1; Bits1 = MemAlloc(sizeof(*Bits1)); if( NULL == Bits1 ) return ERROR_NOT_ENOUGH_MEMORY; (*Bits) = Bits1; Bits1->Size = nBits; Bits1->AllocSize = (nBits + 8)/8; Bits1->nSet = 0; Bits1->Mask = NULL; Bits1->nDirtyOps = 0; return ERROR_SUCCESS; } DWORD _inline MemBit1Cleanup( IN PM_BITMASK1 Bits ) { if( Bits->Mask ) MemFree(Bits->Mask); MemFree(Bits); return ERROR_SUCCESS; } DWORD _inline MemBit1SetAll( IN OUT PM_BITMASK1 Bits ) { Bits->nDirtyOps ++; Bits->nSet = Bits->Size; if( Bits->Mask ) { MemFree(Bits->Mask); Bits->Mask = NULL; } return ERROR_SUCCESS; } DWORD _inline MemBit1ClearAll( IN OUT PM_BITMASK1 Bits ) { Bits->nDirtyOps ++; Bits->nSet = 0; if( Bits->Mask ) { MemFree(Bits->Mask); Bits->Mask = NULL; } return ERROR_SUCCESS; } // Be careful - the same set of masks are used in regread.c -- don't change this!!!! static DWORD Masks[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; DWORD MemBit1SetOrClear( IN OUT PM_BITMASK1 Bits, IN DWORD Location, IN BOOL fSet, OUT LPBOOL fOldState // OPTIONAL ) { BOOL OldState; Bits->nDirtyOps ++; if( 0 == Bits->nSet ) { // No existing bit, so it must all be clear.. if( fOldState ) *fOldState = FALSE; if( !fSet ) return ERROR_SUCCESS; // need to set the bit.. if we are setting only bit, don't bother.. Require(Bits->Size != 0); if( 1 == Bits->Size ) { Bits->nSet = 1; return ERROR_SUCCESS; } // we have to allocate stuff to set the bit.. Bits->Mask = MemAlloc(Bits->AllocSize); if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY; memset(Bits->Mask, 0, Bits->AllocSize); } if( Bits->Size == Bits->nSet ) { // All existing bits set, so prior state is "Set" if( fOldState ) *fOldState = TRUE; if( fSet ) return ERROR_SUCCESS; // check to see if we got only one bit to clear, then we don't have to do nothing if( 1 == Bits->Size ) { Bits->nSet = 0; return ERROR_SUCCESS; } // we have to allocate memory for teh bitmap.. Bits->Mask = MemAlloc(Bits->AllocSize); if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY; memset(Bits->Mask, 0xFF, Bits->AllocSize); } OldState = (Bits->Mask[Location/8] & Masks[Location%8])?TRUE:FALSE; if( fOldState ) *fOldState = OldState; if( fSet == OldState ) return ERROR_SUCCESS; if( fSet ) { if( Bits->Size == ++Bits->nSet ) { if(Bits->Mask ) MemFree(Bits->Mask); Bits->Mask = NULL; } else { Bits->Mask[Location/8] |= Masks[Location%8]; } } else { if( 0 == --Bits->nSet ) { if(Bits->Mask) MemFree(Bits->Mask); Bits->Mask = NULL; } else { Bits->Mask[Location/8] &= ~Masks[Location%8]; } } return ERROR_SUCCESS; } BOOL _inline MemBit1IsSet( IN PM_BITMASK1 Bits, IN DWORD Location ) { if( 0 == Bits->nSet ) return FALSE; if( Bits->Size == Bits->nSet ) return TRUE; if( Bits->Mask[Location/8] & Masks[Location%8] ) return TRUE; return FALSE; } DWORD _inline IsExcluded( IN OUT DWORD *Try, // this is updated to 1 less than end of excl IN DWORD StartAddress, IN PARRAY Exclusions ) { DWORD Error; ARRAY_LOCATION Loc; PM_EXCL Excl; if( NULL == Exclusions ) return FALSE; Error = MemArrayInitLoc(Exclusions, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Error = MemArrayGetElement(Exclusions, &Loc, &Excl); Error = MemArrayNextLoc(Exclusions, &Loc); if( Excl->Start > StartAddress + *Try ) continue; if( Excl->End < StartAddress + *Try ) continue; *Try = Excl->End-StartAddress; return TRUE; } return FALSE; } DWORD _inline MemBit1GetSomeClearedBit( IN OUT PM_BITMASK1 Bits, OUT LPDWORD Offset, IN BOOL fAcquire, // is this address to be taken or just looked up? IN DWORD StartAddress, IN PARRAY Exclusions ) { DWORD i; DWORD j; DWORD Error; DWORD OldState; if( Bits->Size == Bits->nSet ) return ERROR_FILE_NOT_FOUND; if( 0 == Bits->nSet ) { // got some memory.. for( i = 0; i < Bits->Size ; i ++ ) { if( !IsExcluded(&i, StartAddress, Exclusions) ) break; } if( i >= Bits->Size ) { // we got no space at all? how odd? return ERROR_FILE_NOT_FOUND; } // bit "i" is free for us!! Error = MemBit1SetOrClear(Bits, i, TRUE, &OldState); Require( ERROR_SUCCESS == Error ); if( ERROR_SUCCESS == Error ) *Offset = i; return Error; } for( i = 0 ; i < Bits->AllocSize ; i ++ ) { if( 0xFF != Bits->Mask[i] ) { // if "i" is part of an exclusion, skip to end of exclusion for( j = 0; j < 8; j ++ ) { if( !(Bits->Mask[i] & Masks[j] )){// available in the bitmask, but need to check if excluded.. DWORD x; x = 8*i + j; // this is the actual bit position in the bitmask if( !IsExcluded(&x, StartAddress, Exclusions) ) break; // this address is not excluded either.. j = x % 8; // choose the right offset after exclusion if( x > 8*i + 7 ) { j = 8; i = -1 + x/8; break; } } } if( j < 8 ) break; // found a good location.. } } if( i >= Bits->AllocSize ) return ERROR_FILE_NOT_FOUND; Require( (j <= 7) ); *Offset = j + 8*i; if( *Offset >= Bits->Size ) return ERROR_FILE_NOT_FOUND; if( fAcquire ) { if( Bits->Size == ++ Bits->nSet ) { if( Bits->Mask ) MemFree(Bits->Mask); Bits->Mask = NULL; } else { Bits->Mask[i] |= Masks[j]; } Bits->nDirtyOps ++; } return ERROR_SUCCESS; } DWORD _inline MemBit1GetSize( IN PM_BITMASK1 Bits ) { return Bits->Size; } DWORD _inline MemBit1GetSetBitsInRange( IN PM_BITMASK1 Bits, IN DWORD dwFrom, IN DWORD dwTo ) { DWORD i; DWORD nOnes; // simple case: no bits set to 1 if (Bits->nSet == 0) return 0; // simple case: all bits set to 1 if (Bits->nSet == Bits->Size) return dwTo - dwFrom + 1; // we have both types of bits; scan all the bytes concerned for (nOnes = 0, i = dwFrom>>3; i <= dwTo>>3; i++) { BYTE Byte, Dup; // dwFrom and dwTo should both be in the interval [0 .. Bits->Size-1] Byte = Bits->Mask[i]; if (i == (dwFrom>>3)) { // dwFrom // v // if first byte in the range: ...|...[.....|... // mask Byte with 000 11111 Byte &= ~((1 << (dwFrom & 0x00000007)) - 1); } if (i == (dwTo>>3)) { // if last byte in the range: ...|......]..|... // mask Byte with 111111 00 // ^ // dwTo Byte &= (1 << ((dwTo & 0x00000007) + 1)) - 1; } // now compute the nb. of '1' bits from the Byte. // log(8) algorithm Byte = (Byte & 0x55) + ((Byte & 0xAA) >> 1); Byte = (Byte & 0x33) + ((Byte & 0xCC) >> 2); Byte = (Byte & 0x0f) + ((Byte & 0xF0) >> 4); nOnes += Byte; } return nOnes; } DWORD _inline MemBit1GetSetBitsSize( // n Set bits in this bitmask ? IN PM_BITMASK1 Bits ) { return Bits->nSet; } DWORD _inline MemBit1DelBits( IN OUT PM_BITMASK1 Bits, IN DWORD nBits, // new size after contraction IN BOOL fEnd // delete from end or start ? ) { LPBYTE Mask; DWORD Diff; DWORD i; LONG j; Bits->nDirtyOps ++; Diff = Bits->Size - nBits; if( Bits->Size == Bits->nSet ) { Bits->Size = Bits->nSet = nBits; Bits->AllocSize = (nBits + 8)/8; Require(Bits->Mask == NULL); return ERROR_SUCCESS; } if( 0 == Bits->nSet ) { Bits->AllocSize = (nBits+8)/8; Bits->Size = nBits; Require(Bits->Mask == NULL); return ERROR_SUCCESS; } Bits->Size = nBits; if( fEnd && Bits->AllocSize == (nBits+8)/8) { return ERROR_SUCCESS; } Mask = MemAlloc((nBits+8)/8); if( NULL == Mask ) { Require(FALSE); // what to do? lets live with it Mask = Bits->Mask; // just use existing mask } else { memset(Mask, 0, (nBits+8)/8); } Bits->AllocSize = (nBits +8)/8; if( fEnd ) { memmove(Mask, Bits->Mask, Bits->AllocSize); if(Mask != Bits->Mask ) MemFree(Bits->Mask); Bits->Mask = Mask; Bits->nSet = 0; for( i = 0; i < Bits->Size ; i ++ ) // re-calculate # of set bits if( Mask[i/8] & Masks[i%8] ) Bits->nSet ++; return ERROR_SUCCESS; } Bits->nSet = 0; for( j = Bits->Size-1; j >=0 ; j -- ) { if( Bits->Mask[(j+Diff)/8] & Masks[(j+Diff)%8] ) { Mask[j/8] |= Masks[j%8]; Bits->nSet ++; } else Mask[j/8] &= ~Masks[j%8]; } return ERROR_SUCCESS; } const DWORD MaxBit1Size = MAX_BIT1SIZE; DWORD _inline MemBit2Init( OUT PM_BITMASK2 *Bits, IN DWORD nBits ) { PM_BITMASK2 Bits2; DWORD nBit1; DWORD i; DWORD Error; DWORD RetError; DWORD Offset; Bits2 = MemAlloc(sizeof(*Bits2)); if( NULL == Bits2 ) return ERROR_NOT_ENOUGH_MEMORY; Error = MemArrayInit(&Bits2->Array); Require(ERROR_SUCCESS == Error); *Bits = Bits2; Bits2->Size = nBits; nBit1 = nBits/MaxBit1Size; Bits2->Array.Ptrs = MemAlloc( sizeof( LPVOID ) * nBit1 ); if ( NULL == Bits2->Array.Ptrs ) { return ERROR_NOT_ENOUGH_MEMORY; } Bits2->Array.nAllocated = nBit1; for( i = 0; i < nBit1; i ++ ) { PM_BITMASK1 Bit1; Error = MemBit1Init(&Bit1, MaxBit1Size); if( ERROR_SUCCESS != Error) break; Error = MemArrayAddElement(&Bits2->Array,Bit1); if( ERROR_SUCCESS != Error) break; Bit1->Offset = i * MaxBit1Size; } if( ERROR_SUCCESS == Error ) { PM_BITMASK1 Bit1; MemArrayInitLoc(&Bits2->Array, &((*Bits)->Loc)); if( 0 == (nBits % MaxBit1Size) ) return ERROR_SUCCESS; Error = MemBit1Init(&Bit1, nBits % MaxBit1Size); if( ERROR_SUCCESS == Error) { Error = MemArrayAddElement(&Bits2->Array, Bit1); Bit1->Offset = i * MaxBit1Size; } if( ERROR_SUCCESS == Error) return ERROR_SUCCESS; } // error, cleanup *Bits = NULL; RetError = Error; { ARRAY_LOCATION Loc; PM_BITMASK1 Bit1; Error = MemArrayInitLoc(&Bits2->Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement( &Bits2->Array, &Loc, (LPVOID*)&Bit1 ); Require(ERROR_SUCCESS == Error); Error = MemBit1Cleanup(Bit1); Require(ERROR_SUCCESS == Error); Error = MemArrayNextLoc(&Bits2->Array, &Loc); } Error = MemArrayCleanup(&Bits2->Array); Require(ERROR_SUCCESS == Error); MemFree(Bits2); } return RetError; } DWORD _inline MemBit2Cleanup( IN PM_BITMASK2 Bits ) { DWORD Error; ARRAY_LOCATION Loc; PM_BITMASK1 Bit1; Require(Bits->Size); Error = MemArrayInitLoc(&Bits->Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement( &Bits->Array, &Loc, &Bit1 ); Require(ERROR_SUCCESS == Error && Bit1); Error = MemBit1Cleanup(Bit1); Require(ERROR_SUCCESS == Error); Error = MemArrayNextLoc(&Bits->Array, &Loc); } Error = MemArrayCleanup(&Bits->Array); Require(ERROR_SUCCESS == Error); MemFree(Bits); return ERROR_SUCCESS; } DWORD _inline MemBit2SetOrClearAll( IN OUT PM_BITMASK2 Bits, IN BOOL fSet ) { ARRAY_LOCATION Loc; DWORD Error; PM_BITMASK1 Bit1; AssertRet(Bits, ERROR_INVALID_PARAMETER); Error = MemArrayInitLoc(&Bits->Array, &Loc); while( ERROR_FILE_NOT_FOUND != Error ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement( &Bits->Array, &Loc, &Bit1 ); Require(ERROR_SUCCESS == Error && NULL != Bit1); if( fSet ) { Error = MemBit1SetAll(Bit1); } else { Error = MemBit1ClearAll(Bit1); } Require(ERROR_SUCCESS == Error); } return ERROR_SUCCESS; } DWORD MemBit2SetOrClear( IN OUT PM_BITMASK2 Bits, IN DWORD Location, IN BOOL fSet, OUT LPBOOL fOldState ) { ARRAY_LOCATION Loc; DWORD Error; DWORD SkippedSize; DWORD Size; DWORD Start, Mid, End; PM_BITMASK1 Bit1; AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER); //: need to expose a binary search in the array.h module.... Start = 0; End = MemArraySize(&Bits->Array); while( Start + 1 < End) { Mid = (Start + End)/2; Bit1 = Bits->Array.Ptrs[Mid]; if( Bit1->Offset <= Location ) { Start = Mid; } else { End = Mid; } } Require( Start <= MemArraySize(&Bits->Array)); Bit1 = Bits->Array.Ptrs[Start]; Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size); return( MemBit1SetOrClear( Bit1, Location - Bit1 -> Offset, fSet, fOldState ) ); } BOOL _inline MemBit2IsSet( IN OUT PM_BITMASK2 Bits, IN DWORD Location ) { ARRAY_LOCATION Loc; DWORD Error; DWORD SkippedSize; DWORD Size; DWORD Start, Mid, End; PM_BITMASK1 Bit1; AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER); //: need to expose binary search in the array.h module Start = 0; End = MemArraySize(&Bits->Array); while( Start + 1 < End ) { Mid = (Start + End)/2; Bit1 = Bits->Array.Ptrs[Mid]; if( Bit1->Offset <= Location ) { Start = Mid; } else { End = Mid; } } Require( Start <= MemArraySize(&Bits->Array) ); Bit1 = Bits->Array.Ptrs[Start]; Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size); return MemBit1IsSet( Bit1, Location - Bit1->Offset ); } DWORD _inline MemBit2GetSize( IN PM_BITMASK2 Bits ) { AssertRet(Bits, ERROR_INVALID_PARAMETER ); return Bits->Size; } DWORD _inline MemBit2GetSetBitsInRange( IN PM_BITMASK2 Bits, IN DWORD dwFrom, IN DWORD dwTo ) { ARRAY_LOCATION Loc; PM_BITMASK1 Bit1; DWORD nOnes; DWORD Error; AssertRet(Bits, ERROR_INVALID_PARAMETER); Error = MemArrayInitLoc(&Bits->Array, &Loc); nOnes = 0; while(ERROR_FILE_NOT_FOUND != Error) { Error = MemArrayGetElement( &Bits->Array, &Loc, &Bit1 ); Require(ERROR_SUCCESS == Error); if (dwTo < Bit1->Offset) break; if (dwFrom < Bit1->Offset + Bit1->Size) { if (dwFrom < Bit1->Offset) dwFrom = Bit1->Offset; nOnes += MemBit1GetSetBitsInRange(Bit1, dwFrom - Bit1->Offset, dwTo < Bit1->Offset + Bit1->Size ? dwTo - Bit1->Offset: Bit1->Size - 1); } Error = MemArrayNextLoc(&Bits->Array, &Loc); } return nOnes; } DWORD _inline MemBit2GetSetBitsSize( IN PM_BITMASK2 Bits ) { ARRAY_LOCATION Loc; DWORD Error; DWORD nSet; PM_BITMASK1 Bit1; AssertRet(Bits, ERROR_INVALID_PARAMETER); nSet = 0; Error = MemArrayInitLoc(&Bits->Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement( &Bits->Array, &Loc, &Bit1 ); Require(ERROR_SUCCESS == Error); nSet += MemBit1GetSetBitsSize(Bit1); Error = MemArrayNextLoc(&Bits->Array, &Loc); } return nSet; } DWORD _inline MemBit2DelBits( IN OUT PM_BITMASK2 Bits, IN DWORD nBitsToDelete, IN BOOL fEnd ) { ARRAY_LOCATION Loc; DWORD i; DWORD Size; DWORD Error; PM_BITMASK1 Bit1, Bit1x; AssertRet(Bits && nBitsToDelete && Bits->Size > nBitsToDelete, ERROR_INVALID_PARAMETER); if( fEnd ) { Error = MemArrayLastLoc(&Bits->Array, &Loc); } else { Error = MemArrayInitLoc(&Bits->Array, &Loc); } Require(ERROR_SUCCESS == Error); while( nBitsToDelete ) { Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1); Require(ERROR_SUCCESS == Error); Size = MemBit1GetSize(Bit1); if( nBitsToDelete >= Size ) { nBitsToDelete -= Size; Bits->Size -= Size; Error = MemBit1Cleanup(Bit1); Require(ERROR_SUCCESS == Error); Error = MemArrayDelElement(&Bits->Array, &Loc, &Bit1x); Require(ERROR_SUCCESS == Error && Bit1x == Bit1); // Reset the ptr to the FIRST/LAST location to read the next element if( fEnd ) { Error = MemArrayLastLoc(&Bits->Array, &Loc); } else { Error = MemArrayInitLoc(&Bits->Array, &Loc); } } else { Size -= nBitsToDelete; Bits->Size -= nBitsToDelete; nBitsToDelete = 0; Error = MemBit1DelBits(Bit1, Size, fEnd); } Require(ERROR_SUCCESS == Error); } Size = 0; Error = MemArrayInitLoc(&Bits->Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1); Require(ERROR_SUCCESS == Error && Bit1); Bit1->Offset = Size; Size += Bit1->Size; Error = MemArrayNextLoc(&Bits->Array, &Loc); } MemArrayInitLoc( &Bits->Array, &Bits->Loc); return NO_ERROR; } DWORD _inline MemBit2AddBits( IN OUT PM_BITMASK2 Bits, IN DWORD nBitsToAdd, IN BOOL fEnd ) { ARRAY_LOCATION Loc; DWORD i; DWORD Size; DWORD Error; PM_BITMASK1 Bit1; AssertRet(Bits && nBitsToAdd, ERROR_INVALID_PARAMETER); while( nBitsToAdd ) { Size = (nBitsToAdd > MaxBit1Size) ? MaxBit1Size : nBitsToAdd; nBitsToAdd -= Size; Error = MemBit1Init(&Bit1, Size); if( ERROR_SUCCESS != Error ) break; if( fEnd ) { Error = MemArrayAddElement( &Bits->Array, Bit1 ); } else { Error = MemArrayInitLoc(&Bits->Array, &Loc); Require(ERROR_SUCCESS == Error); Error = MemArrayInsElement( &Bits->Array, &Loc, Bit1 ); } if( ERROR_SUCCESS != Error ) break; Bits->Size += Size; } Size = 0; Error = MemArrayInitLoc(&Bits->Array, &Loc); while(ERROR_FILE_NOT_FOUND != Error) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1); Require(ERROR_SUCCESS == Error && Bit1); Bit1->Offset = Size; Size += Bit1->Size; Error = MemArrayNextLoc(&Bits->Array, &Loc); } MemArrayInitLoc( &Bits->Array, &Bits->Loc); return NO_ERROR; } DWORD _inline MemBit2GetSomeClearedBit( IN OUT PM_BITMASK2 Bits, OUT LPDWORD Offset, IN BOOL fAcquire, // if we find one, do we Set it? IN DWORD StartAddress, IN PARRAY Exclusions ) { ARRAY_LOCATION Loc; DWORD Size; DWORD Error; DWORD nBit1s; PM_BITMASK1 Bit1; AssertRet(Bits && Offset, ERROR_INVALID_PARAMETER); nBit1s = MemArraySize(&Bits->Array); while( nBit1s-- != 0 ) { Error = MemArrayGetElement(&Bits->Array, &Bits->Loc, (LPVOID *)&Bit1); Require(ERROR_SUCCESS == Error); Error = MemBit1GetSomeClearedBit(Bit1, &Size, fAcquire, StartAddress+Bit1->Offset, Exclusions); if( ERROR_SUCCESS == Error ) { *Offset = Bit1->Offset + Size; return ERROR_SUCCESS; } Error = MemArrayNextLoc(&Bits->Array, &Bits->Loc); if( ERROR_SUCCESS != Error ) { Error = MemArrayInitLoc(&Bits->Array, &Bits->Loc); Require( ERROR_SUCCESS == Error ); } } return ERROR_FILE_NOT_FOUND; } //BeginExport(function) DWORD MemBitInit( OUT PM_BITMASK *Bits, IN DWORD nBits ) //EndExport(function) { AssertRet(Bits && nBits, ERROR_INVALID_PARAMETER); return MemBit2Init(Bits,nBits); } //BeginExport(function) DWORD MemBitCleanup( IN OUT PM_BITMASK Bits ) //EndExport(function) { AssertRet(Bits, ERROR_INVALID_PARAMETER); return MemBit2Cleanup(Bits); } //BeginExport(function) DWORD MemBitSetOrClearAll( IN OUT PM_BITMASK Bits, IN BOOL fSet ) //EndExport(function) { return MemBit2SetOrClearAll(Bits,fSet); } //BeginExport(function) DWORD MemBitSetOrClear( IN OUT PM_BITMASK Bits, IN DWORD Location, IN BOOL fSet, IN LPBOOL fOldState ) //EndExport(function) { return MemBit2SetOrClear(Bits,Location,fSet, fOldState); } //BeginExport(function) BOOL MemBitIsSet( IN OUT PM_BITMASK Bits, IN DWORD Location ) //EndExport(function) { BOOL Test; Test = MemBit2IsSet(Bits, Location); return Test; } //BeginExport(function) DWORD MemBitGetSize( IN PM_BITMASK Bits ) //EndExport(function) { return MemBit2GetSize(Bits); } //BeginExport(function) DWORD MemBitGetSetBitsInRange( IN PM_BITMASK Bits, IN DWORD dwFrom, IN DWORD dwTo ) //EndExport(function) { return MemBit2GetSetBitsInRange(Bits, dwFrom, dwTo); } //BeginExport(function) DWORD MemBitGetSetBitsSize( IN PM_BITMASK Bits ) //EndExport(function) { return MemBit2GetSetBitsSize(Bits); } //BeginExport(function) DWORD MemBitAddOrDelBits( IN OUT PM_BITMASK Bits, IN DWORD nBitsToAddOrDelete, IN BOOL fAdd, IN BOOL fEnd ) //EndExport(function) { if( fAdd ) return MemBit2AddBits(Bits, nBitsToAddOrDelete, fEnd); return MemBit2DelBits(Bits,nBitsToAddOrDelete, fEnd); } //BeginExport(function) DWORD MemBitGetSomeClearedBit( IN OUT PM_BITMASK Bits, OUT DWORD *Offset, IN BOOL fAcquire, // Acquire or just lookup? IN DWORD StartAddress, IN PARRAY Exclusions ) //EndExport(function) { return MemBit2GetSomeClearedBit(Bits,Offset,fAcquire, StartAddress, Exclusions); } //BeginExport(function) DWORD MemBitConvertToCluster( IN PM_BITMASK Bits, IN DWORD StartAddress, OUT LPBYTE *InUseClusters, OUT DWORD *InUseClustersSize, OUT LPBYTE *UsedClusters, OUT DWORD *UsedClustersSize ) //EndExport(function) { DWORD Error; DWORD Cluster; DWORD i, j; DWORD nBits; DWORD nBit1s; DWORD Size; DWORD UsedSize; DWORD InUseSize; LPDWORD Used; LPDWORD InUse; PM_BITMASK1 Bit1; ARRAY_LOCATION Loc; nBits = MemBitGetSize(Bits); if( 0 == nBits || 0 == MemBitGetSetBitsSize(Bits) ) { InUse = MemAlloc(sizeof(DWORD)); Used = MemAlloc(sizeof(DWORD)); if( NULL == InUse || NULL == Used ) { if( InUse ) MemFree(InUse); if( Used ) MemFree(Used); Require(FALSE); return ERROR_NOT_ENOUGH_MEMORY; } *Used = *InUse = 0; *InUseClusters = (LPBYTE)InUse; *UsedClusters = (LPBYTE)Used; *InUseClustersSize = *UsedClustersSize = sizeof(DWORD); return ERROR_SUCCESS; } nBit1s = MemArraySize(&Bits->Array); Require(nBit1s); Error = MemArrayInitLoc(&Bits->Array, &Loc); UsedSize = InUseSize = 1; // no matter what, we always use a DWORD for total size for(i = 0; i < nBit1s ; i ++ ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1); Require(ERROR_SUCCESS == Error && Bit1); Error = MemArrayNextLoc(&Bits->Array, &Loc); // : Dont touch Bit1 directly like below? not really clean if( 0 == Bit1->nSet ) continue; // no bit is set, nothing to do.. if( Bit1->Size == Bit1->nSet ) { // all bits set, nothing to do except for few odd bits UsedSize += Bit1->Size/32; if( Bit1->Size % 32 ) InUseSize+=2; // fill the odd bits in InUse so that we dont mark extra bits as used continue; } for( j = 0; j < Bit1->Size/32; j ++ ) { if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) { UsedSize ++; // this 32-bit is completely filled } else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) { InUseSize += 2; // this 32 bit is partially filled, not quite empty } } if( j * 32 < Bit1->Size ) InUseSize +=2; // for the last few bits.. } InUse = MemAlloc(InUseSize * sizeof(DWORD)); Used = MemAlloc(UsedSize * sizeof(DWORD)); if( NULL == Used || NULL == InUse ) { if( InUse ) MemFree(InUse); if( Used ) MemFree(Used); return ERROR_NOT_ENOUGH_MEMORY; } *InUseClustersSize = sizeof(DWORD)*InUseSize; // fill in the sizes and ptrs to be returned.. *InUseClusters = (LPBYTE)InUse; *UsedClusters = (LPBYTE)Used; *UsedClustersSize = sizeof(DWORD)*UsedSize; Error = MemArrayInitLoc(&Bits->Array, &Loc); UsedSize = InUseSize = 1; for(i = 0; i < nBit1s ; i ++ ) { Require(ERROR_SUCCESS == Error); Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1); Require(ERROR_SUCCESS == Error && Bit1); Error = MemArrayNextLoc(&Bits->Array, &Loc); // Dont touch Bit1 directly like below? not really clean if( 0 == Bit1->nSet ) { // all bits clear ==> just ignore StartAddress += Bit1->Size; continue; } if( Bit1->nSet == Bit1->Size ) { // handle all bits set here (loose bits need to be handled later) for( j = 0; j < Bit1->Size/32; j ++ ) { Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8; } } else { for( j = 0; j < Bit1->Size/32; j ++ ) { if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) { Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8; } else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) { #ifdef _X86_ // on X86, the first byte is the lowest order byte.. Cluster = ((LPDWORD)(Bit1->Mask))[j]; #else // it maynot be so on other machines, so combine the bytes manually.. Cluster = Bit1->Mask[j*sizeof(DWORD)]; Cluster |= (Bit1->Mask[j*sizeof(DWORD)+1]) << 8; Cluster |= (Bit1->Mask[j*sizeof(DWORD)+2]) << 16; Cluster |= (Bit1->Mask[j*sizeof(DWORD)+3]) << 24; #endif InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8; InUse[InUseSize++] = Cluster; } } } if( j * 32 < Bit1->Size ) { // copy the last few bits off.. InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8; Cluster = 0; j *= 32; while( j < Bit1->Size ) { if( MemBit1IsSet(Bit1, j) ) Cluster |= (1 << (j%32)); j ++; } InUse[InUseSize++] = Cluster; } StartAddress += Bit1->Size; // move the start address fwd for the next set.. } InUse[0] = (InUseSize -1)/2; // size in header does not include itself Used[0] = UsedSize -1; // it is just the # of CLUSTERS.. Require(InUseSize*sizeof(DWORD) == *InUseClustersSize); Require(UsedSize*sizeof(DWORD) == *UsedClustersSize); return ERROR_SUCCESS; } //================================================================================ // End of file //================================================================================