Leaked source code of windows server 2003
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.

1157 lines
33 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: implements the basic structures for bitmasks
  5. // ThreadSafe: no
  6. // Locks: none
  7. // Please read stdinfo.txt for programming style.
  8. //================================================================================
  9. #include <mm.h>
  10. #include <array.h>
  11. #include "bitmask.h"
  12. DWORD _inline
  13. MemBit1Init(
  14. OUT PM_BITMASK1 *Bits,
  15. IN DWORD nBits
  16. )
  17. {
  18. PM_BITMASK1 Bits1;
  19. Bits1 = MemAlloc(sizeof(*Bits1));
  20. if( NULL == Bits1 ) return ERROR_NOT_ENOUGH_MEMORY;
  21. (*Bits) = Bits1;
  22. Bits1->Size = nBits;
  23. Bits1->AllocSize = (nBits + 8)/8;
  24. Bits1->nSet = 0;
  25. Bits1->Mask = NULL;
  26. Bits1->nDirtyOps = 0;
  27. return ERROR_SUCCESS;
  28. }
  29. DWORD _inline
  30. MemBit1Cleanup(
  31. IN PM_BITMASK1 Bits
  32. )
  33. {
  34. if( Bits->Mask ) MemFree(Bits->Mask);
  35. MemFree(Bits);
  36. return ERROR_SUCCESS;
  37. }
  38. DWORD _inline
  39. MemBit1SetAll(
  40. IN OUT PM_BITMASK1 Bits
  41. )
  42. {
  43. Bits->nDirtyOps ++;
  44. Bits->nSet = Bits->Size;
  45. if( Bits->Mask ) {
  46. MemFree(Bits->Mask);
  47. Bits->Mask = NULL;
  48. }
  49. return ERROR_SUCCESS;
  50. }
  51. DWORD _inline
  52. MemBit1ClearAll(
  53. IN OUT PM_BITMASK1 Bits
  54. )
  55. {
  56. Bits->nDirtyOps ++;
  57. Bits->nSet = 0;
  58. if( Bits->Mask ) {
  59. MemFree(Bits->Mask);
  60. Bits->Mask = NULL;
  61. }
  62. return ERROR_SUCCESS;
  63. }
  64. // Be careful - the same set of masks are used in regread.c -- don't change this!!!!
  65. static DWORD Masks[] = {
  66. 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
  67. };
  68. DWORD
  69. MemBit1SetOrClear(
  70. IN OUT PM_BITMASK1 Bits,
  71. IN DWORD Location,
  72. IN BOOL fSet,
  73. OUT LPBOOL fOldState // OPTIONAL
  74. )
  75. {
  76. BOOL OldState;
  77. Bits->nDirtyOps ++;
  78. if( 0 == Bits->nSet ) {
  79. // No existing bit, so it must all be clear..
  80. if( fOldState ) *fOldState = FALSE;
  81. if( !fSet ) return ERROR_SUCCESS;
  82. // need to set the bit.. if we are setting only bit, don't bother..
  83. Require(Bits->Size != 0);
  84. if( 1 == Bits->Size ) {
  85. Bits->nSet = 1;
  86. return ERROR_SUCCESS;
  87. }
  88. // we have to allocate stuff to set the bit..
  89. Bits->Mask = MemAlloc(Bits->AllocSize);
  90. if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY;
  91. memset(Bits->Mask, 0, Bits->AllocSize);
  92. }
  93. if( Bits->Size == Bits->nSet ) {
  94. // All existing bits set, so prior state is "Set"
  95. if( fOldState ) *fOldState = TRUE;
  96. if( fSet ) return ERROR_SUCCESS;
  97. // check to see if we got only one bit to clear, then we don't have to do nothing
  98. if( 1 == Bits->Size ) {
  99. Bits->nSet = 0;
  100. return ERROR_SUCCESS;
  101. }
  102. // we have to allocate memory for teh bitmap..
  103. Bits->Mask = MemAlloc(Bits->AllocSize);
  104. if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY;
  105. memset(Bits->Mask, 0xFF, Bits->AllocSize);
  106. }
  107. OldState = (Bits->Mask[Location/8] & Masks[Location%8])?TRUE:FALSE;
  108. if( fOldState ) *fOldState = OldState;
  109. if( fSet == OldState ) return ERROR_SUCCESS;
  110. if( fSet ) {
  111. if( Bits->Size == ++Bits->nSet ) {
  112. if(Bits->Mask ) MemFree(Bits->Mask);
  113. Bits->Mask = NULL;
  114. } else {
  115. Bits->Mask[Location/8] |= Masks[Location%8];
  116. }
  117. } else {
  118. if( 0 == --Bits->nSet ) {
  119. if(Bits->Mask) MemFree(Bits->Mask);
  120. Bits->Mask = NULL;
  121. } else {
  122. Bits->Mask[Location/8] &= ~Masks[Location%8];
  123. }
  124. }
  125. return ERROR_SUCCESS;
  126. }
  127. BOOL _inline
  128. MemBit1IsSet(
  129. IN PM_BITMASK1 Bits,
  130. IN DWORD Location
  131. )
  132. {
  133. if( 0 == Bits->nSet ) return FALSE;
  134. if( Bits->Size == Bits->nSet ) return TRUE;
  135. if( Bits->Mask[Location/8] & Masks[Location%8] )
  136. return TRUE;
  137. return FALSE;
  138. }
  139. DWORD _inline
  140. IsExcluded(
  141. IN OUT DWORD *Try, // this is updated to 1 less than end of excl
  142. IN DWORD StartAddress,
  143. IN PARRAY Exclusions
  144. )
  145. {
  146. DWORD Error;
  147. ARRAY_LOCATION Loc;
  148. PM_EXCL Excl;
  149. if( NULL == Exclusions ) return FALSE;
  150. Error = MemArrayInitLoc(Exclusions, &Loc);
  151. while(ERROR_FILE_NOT_FOUND != Error) {
  152. Error = MemArrayGetElement(Exclusions, &Loc, &Excl);
  153. Error = MemArrayNextLoc(Exclusions, &Loc);
  154. if( Excl->Start > StartAddress + *Try ) continue;
  155. if( Excl->End < StartAddress + *Try ) continue;
  156. *Try = Excl->End-StartAddress;
  157. return TRUE;
  158. }
  159. return FALSE;
  160. }
  161. DWORD _inline
  162. MemBit1GetSomeClearedBit(
  163. IN OUT PM_BITMASK1 Bits,
  164. OUT LPDWORD Offset,
  165. IN BOOL fAcquire, // is this address to be taken or just looked up?
  166. IN DWORD StartAddress,
  167. IN PARRAY Exclusions
  168. )
  169. {
  170. DWORD i;
  171. DWORD j;
  172. DWORD Error;
  173. DWORD OldState;
  174. if( Bits->Size == Bits->nSet ) return ERROR_FILE_NOT_FOUND;
  175. if( 0 == Bits->nSet ) { // got some memory..
  176. for( i = 0; i < Bits->Size ; i ++ ) {
  177. if( !IsExcluded(&i, StartAddress, Exclusions) )
  178. break;
  179. }
  180. if( i >= Bits->Size ) { // we got no space at all? how odd?
  181. return ERROR_FILE_NOT_FOUND;
  182. }
  183. // bit "i" is free for us!!
  184. Error = MemBit1SetOrClear(Bits, i, TRUE, &OldState);
  185. Require( ERROR_SUCCESS == Error );
  186. if( ERROR_SUCCESS == Error ) *Offset = i;
  187. return Error;
  188. }
  189. for( i = 0 ; i < Bits->AllocSize ; i ++ ) {
  190. if( 0xFF != Bits->Mask[i] ) { // if "i" is part of an exclusion, skip to end of exclusion
  191. for( j = 0; j < 8; j ++ ) {
  192. if( !(Bits->Mask[i] & Masks[j] )){// available in the bitmask, but need to check if excluded..
  193. DWORD x;
  194. x = 8*i + j; // this is the actual bit position in the bitmask
  195. if( !IsExcluded(&x, StartAddress, Exclusions) )
  196. break; // this address is not excluded either..
  197. j = x % 8; // choose the right offset after exclusion
  198. if( x > 8*i + 7 ) { j = 8; i = -1 + x/8; break; }
  199. }
  200. }
  201. if( j < 8 ) break; // found a good location..
  202. }
  203. }
  204. if( i >= Bits->AllocSize ) return ERROR_FILE_NOT_FOUND;
  205. Require( (j <= 7) );
  206. *Offset = j + 8*i;
  207. if( *Offset >= Bits->Size ) return ERROR_FILE_NOT_FOUND;
  208. if( fAcquire ) {
  209. if( Bits->Size == ++ Bits->nSet ) {
  210. if( Bits->Mask ) MemFree(Bits->Mask);
  211. Bits->Mask = NULL;
  212. } else {
  213. Bits->Mask[i] |= Masks[j];
  214. }
  215. Bits->nDirtyOps ++;
  216. }
  217. return ERROR_SUCCESS;
  218. }
  219. DWORD _inline
  220. MemBit1GetSize(
  221. IN PM_BITMASK1 Bits
  222. )
  223. {
  224. return Bits->Size;
  225. }
  226. DWORD _inline
  227. MemBit1GetSetBitsInRange(
  228. IN PM_BITMASK1 Bits,
  229. IN DWORD dwFrom,
  230. IN DWORD dwTo
  231. )
  232. {
  233. DWORD i;
  234. DWORD nOnes;
  235. // simple case: no bits set to 1
  236. if (Bits->nSet == 0)
  237. return 0;
  238. // simple case: all bits set to 1
  239. if (Bits->nSet == Bits->Size)
  240. return dwTo - dwFrom + 1;
  241. // we have both types of bits; scan all the bytes concerned
  242. for (nOnes = 0, i = dwFrom>>3; i <= dwTo>>3; i++)
  243. {
  244. BYTE Byte, Dup;
  245. // dwFrom and dwTo should both be in the interval [0 .. Bits->Size-1]
  246. Byte = Bits->Mask[i];
  247. if (i == (dwFrom>>3))
  248. {
  249. // dwFrom
  250. // v
  251. // if first byte in the range: ...|...[.....|...
  252. // mask Byte with 000 11111
  253. Byte &= ~((1 << (dwFrom & 0x00000007)) - 1);
  254. }
  255. if (i == (dwTo>>3))
  256. {
  257. // if last byte in the range: ...|......]..|...
  258. // mask Byte with 111111 00
  259. // ^
  260. // dwTo
  261. Byte &= (1 << ((dwTo & 0x00000007) + 1)) - 1;
  262. }
  263. // now compute the nb. of '1' bits from the Byte.
  264. // log(8) algorithm
  265. Byte = (Byte & 0x55) + ((Byte & 0xAA) >> 1);
  266. Byte = (Byte & 0x33) + ((Byte & 0xCC) >> 2);
  267. Byte = (Byte & 0x0f) + ((Byte & 0xF0) >> 4);
  268. nOnes += Byte;
  269. }
  270. return nOnes;
  271. }
  272. DWORD _inline
  273. MemBit1GetSetBitsSize( // n Set bits in this bitmask ?
  274. IN PM_BITMASK1 Bits
  275. )
  276. {
  277. return Bits->nSet;
  278. }
  279. DWORD _inline
  280. MemBit1DelBits(
  281. IN OUT PM_BITMASK1 Bits,
  282. IN DWORD nBits, // new size after contraction
  283. IN BOOL fEnd // delete from end or start ?
  284. )
  285. {
  286. LPBYTE Mask;
  287. DWORD Diff;
  288. DWORD i;
  289. LONG j;
  290. Bits->nDirtyOps ++;
  291. Diff = Bits->Size - nBits;
  292. if( Bits->Size == Bits->nSet ) {
  293. Bits->Size = Bits->nSet = nBits;
  294. Bits->AllocSize = (nBits + 8)/8;
  295. Require(Bits->Mask == NULL);
  296. return ERROR_SUCCESS;
  297. }
  298. if( 0 == Bits->nSet ) {
  299. Bits->AllocSize = (nBits+8)/8;
  300. Bits->Size = nBits;
  301. Require(Bits->Mask == NULL);
  302. return ERROR_SUCCESS;
  303. }
  304. Bits->Size = nBits;
  305. if( fEnd && Bits->AllocSize == (nBits+8)/8) {
  306. return ERROR_SUCCESS;
  307. }
  308. Mask = MemAlloc((nBits+8)/8);
  309. if( NULL == Mask ) {
  310. Require(FALSE); // what to do? lets live with it
  311. Mask = Bits->Mask; // just use existing mask
  312. } else {
  313. memset(Mask, 0, (nBits+8)/8);
  314. }
  315. Bits->AllocSize = (nBits +8)/8;
  316. if( fEnd ) {
  317. memmove(Mask, Bits->Mask, Bits->AllocSize);
  318. if(Mask != Bits->Mask ) MemFree(Bits->Mask);
  319. Bits->Mask = Mask;
  320. Bits->nSet = 0;
  321. for( i = 0; i < Bits->Size ; i ++ ) // re-calculate # of set bits
  322. if( Mask[i/8] & Masks[i%8] ) Bits->nSet ++;
  323. return ERROR_SUCCESS;
  324. }
  325. Bits->nSet = 0;
  326. for( j = Bits->Size-1; j >=0 ; j -- ) {
  327. if( Bits->Mask[(j+Diff)/8] & Masks[(j+Diff)%8] ) {
  328. Mask[j/8] |= Masks[j%8];
  329. Bits->nSet ++;
  330. } else Mask[j/8] &= ~Masks[j%8];
  331. }
  332. return ERROR_SUCCESS;
  333. }
  334. const DWORD MaxBit1Size = MAX_BIT1SIZE;
  335. DWORD _inline
  336. MemBit2Init(
  337. OUT PM_BITMASK2 *Bits,
  338. IN DWORD nBits
  339. )
  340. {
  341. PM_BITMASK2 Bits2;
  342. DWORD nBit1;
  343. DWORD i;
  344. DWORD Error;
  345. DWORD RetError;
  346. DWORD Offset;
  347. Bits2 = MemAlloc(sizeof(*Bits2));
  348. if( NULL == Bits2 ) return ERROR_NOT_ENOUGH_MEMORY;
  349. Error = MemArrayInit(&Bits2->Array);
  350. Require(ERROR_SUCCESS == Error);
  351. *Bits = Bits2;
  352. Bits2->Size = nBits;
  353. nBit1 = nBits/MaxBit1Size;
  354. Bits2->Array.Ptrs = MemAlloc( sizeof( LPVOID ) * nBit1 );
  355. if ( NULL == Bits2->Array.Ptrs ) {
  356. return ERROR_NOT_ENOUGH_MEMORY;
  357. }
  358. Bits2->Array.nAllocated = nBit1;
  359. for( i = 0; i < nBit1; i ++ ) {
  360. PM_BITMASK1 Bit1;
  361. Error = MemBit1Init(&Bit1, MaxBit1Size);
  362. if( ERROR_SUCCESS != Error) break;
  363. Error = MemArrayAddElement(&Bits2->Array,Bit1);
  364. if( ERROR_SUCCESS != Error) break;
  365. Bit1->Offset = i * MaxBit1Size;
  366. }
  367. if( ERROR_SUCCESS == Error ) {
  368. PM_BITMASK1 Bit1;
  369. MemArrayInitLoc(&Bits2->Array, &((*Bits)->Loc));
  370. if( 0 == (nBits % MaxBit1Size) ) return ERROR_SUCCESS;
  371. Error = MemBit1Init(&Bit1, nBits % MaxBit1Size);
  372. if( ERROR_SUCCESS == Error) {
  373. Error = MemArrayAddElement(&Bits2->Array, Bit1);
  374. Bit1->Offset = i * MaxBit1Size;
  375. }
  376. if( ERROR_SUCCESS == Error) return ERROR_SUCCESS;
  377. }
  378. // error, cleanup
  379. *Bits = NULL;
  380. RetError = Error;
  381. {
  382. ARRAY_LOCATION Loc;
  383. PM_BITMASK1 Bit1;
  384. Error = MemArrayInitLoc(&Bits2->Array, &Loc);
  385. while(ERROR_FILE_NOT_FOUND != Error) {
  386. Require(ERROR_SUCCESS == Error);
  387. Error = MemArrayGetElement(
  388. &Bits2->Array,
  389. &Loc,
  390. (LPVOID*)&Bit1
  391. );
  392. Require(ERROR_SUCCESS == Error);
  393. Error = MemBit1Cleanup(Bit1);
  394. Require(ERROR_SUCCESS == Error);
  395. Error = MemArrayNextLoc(&Bits2->Array, &Loc);
  396. }
  397. Error = MemArrayCleanup(&Bits2->Array);
  398. Require(ERROR_SUCCESS == Error);
  399. MemFree(Bits2);
  400. }
  401. return RetError;
  402. }
  403. DWORD _inline
  404. MemBit2Cleanup(
  405. IN PM_BITMASK2 Bits
  406. )
  407. {
  408. DWORD Error;
  409. ARRAY_LOCATION Loc;
  410. PM_BITMASK1 Bit1;
  411. Require(Bits->Size);
  412. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  413. while(ERROR_FILE_NOT_FOUND != Error) {
  414. Require(ERROR_SUCCESS == Error);
  415. Error = MemArrayGetElement(
  416. &Bits->Array,
  417. &Loc,
  418. &Bit1
  419. );
  420. Require(ERROR_SUCCESS == Error && Bit1);
  421. Error = MemBit1Cleanup(Bit1);
  422. Require(ERROR_SUCCESS == Error);
  423. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  424. }
  425. Error = MemArrayCleanup(&Bits->Array);
  426. Require(ERROR_SUCCESS == Error);
  427. MemFree(Bits);
  428. return ERROR_SUCCESS;
  429. }
  430. DWORD _inline
  431. MemBit2SetOrClearAll(
  432. IN OUT PM_BITMASK2 Bits,
  433. IN BOOL fSet
  434. )
  435. {
  436. ARRAY_LOCATION Loc;
  437. DWORD Error;
  438. PM_BITMASK1 Bit1;
  439. AssertRet(Bits, ERROR_INVALID_PARAMETER);
  440. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  441. while( ERROR_FILE_NOT_FOUND != Error ) {
  442. Require(ERROR_SUCCESS == Error);
  443. Error = MemArrayGetElement(
  444. &Bits->Array,
  445. &Loc,
  446. &Bit1
  447. );
  448. Require(ERROR_SUCCESS == Error && NULL != Bit1);
  449. if( fSet ) {
  450. Error = MemBit1SetAll(Bit1);
  451. } else {
  452. Error = MemBit1ClearAll(Bit1);
  453. }
  454. Require(ERROR_SUCCESS == Error);
  455. }
  456. return ERROR_SUCCESS;
  457. }
  458. DWORD
  459. MemBit2SetOrClear(
  460. IN OUT PM_BITMASK2 Bits,
  461. IN DWORD Location,
  462. IN BOOL fSet,
  463. OUT LPBOOL fOldState
  464. )
  465. {
  466. ARRAY_LOCATION Loc;
  467. DWORD Error;
  468. DWORD SkippedSize;
  469. DWORD Size;
  470. DWORD Start, Mid, End;
  471. PM_BITMASK1 Bit1;
  472. AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER);
  473. //: need to expose a binary search in the array.h module....
  474. Start = 0;
  475. End = MemArraySize(&Bits->Array);
  476. while( Start + 1 < End) {
  477. Mid = (Start + End)/2;
  478. Bit1 = Bits->Array.Ptrs[Mid];
  479. if( Bit1->Offset <= Location ) {
  480. Start = Mid;
  481. } else {
  482. End = Mid;
  483. }
  484. }
  485. Require( Start <= MemArraySize(&Bits->Array));
  486. Bit1 = Bits->Array.Ptrs[Start];
  487. Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size);
  488. return( MemBit1SetOrClear(
  489. Bit1,
  490. Location - Bit1 -> Offset,
  491. fSet,
  492. fOldState ) );
  493. }
  494. BOOL _inline
  495. MemBit2IsSet(
  496. IN OUT PM_BITMASK2 Bits,
  497. IN DWORD Location
  498. )
  499. {
  500. ARRAY_LOCATION Loc;
  501. DWORD Error;
  502. DWORD SkippedSize;
  503. DWORD Size;
  504. DWORD Start, Mid, End;
  505. PM_BITMASK1 Bit1;
  506. AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER);
  507. //: need to expose binary search in the array.h module
  508. Start = 0;
  509. End = MemArraySize(&Bits->Array);
  510. while( Start + 1 < End ) {
  511. Mid = (Start + End)/2;
  512. Bit1 = Bits->Array.Ptrs[Mid];
  513. if( Bit1->Offset <= Location ) {
  514. Start = Mid;
  515. } else {
  516. End = Mid;
  517. }
  518. }
  519. Require( Start <= MemArraySize(&Bits->Array) );
  520. Bit1 = Bits->Array.Ptrs[Start];
  521. Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size);
  522. return MemBit1IsSet(
  523. Bit1,
  524. Location - Bit1->Offset
  525. );
  526. }
  527. DWORD _inline
  528. MemBit2GetSize(
  529. IN PM_BITMASK2 Bits
  530. )
  531. {
  532. AssertRet(Bits, ERROR_INVALID_PARAMETER );
  533. return Bits->Size;
  534. }
  535. DWORD _inline
  536. MemBit2GetSetBitsInRange(
  537. IN PM_BITMASK2 Bits,
  538. IN DWORD dwFrom,
  539. IN DWORD dwTo
  540. )
  541. {
  542. ARRAY_LOCATION Loc;
  543. PM_BITMASK1 Bit1;
  544. DWORD nOnes;
  545. DWORD Error;
  546. AssertRet(Bits, ERROR_INVALID_PARAMETER);
  547. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  548. nOnes = 0;
  549. while(ERROR_FILE_NOT_FOUND != Error)
  550. {
  551. Error = MemArrayGetElement(
  552. &Bits->Array,
  553. &Loc,
  554. &Bit1
  555. );
  556. Require(ERROR_SUCCESS == Error);
  557. if (dwTo < Bit1->Offset)
  558. break;
  559. if (dwFrom < Bit1->Offset + Bit1->Size)
  560. {
  561. if (dwFrom < Bit1->Offset)
  562. dwFrom = Bit1->Offset;
  563. nOnes += MemBit1GetSetBitsInRange(Bit1,
  564. dwFrom - Bit1->Offset,
  565. dwTo < Bit1->Offset + Bit1->Size ? dwTo - Bit1->Offset: Bit1->Size - 1);
  566. }
  567. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  568. }
  569. return nOnes;
  570. }
  571. DWORD _inline
  572. MemBit2GetSetBitsSize(
  573. IN PM_BITMASK2 Bits
  574. )
  575. {
  576. ARRAY_LOCATION Loc;
  577. DWORD Error;
  578. DWORD nSet;
  579. PM_BITMASK1 Bit1;
  580. AssertRet(Bits, ERROR_INVALID_PARAMETER);
  581. nSet = 0;
  582. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  583. while(ERROR_FILE_NOT_FOUND != Error) {
  584. Require(ERROR_SUCCESS == Error);
  585. Error = MemArrayGetElement(
  586. &Bits->Array,
  587. &Loc,
  588. &Bit1
  589. );
  590. Require(ERROR_SUCCESS == Error);
  591. nSet += MemBit1GetSetBitsSize(Bit1);
  592. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  593. }
  594. return nSet;
  595. }
  596. DWORD _inline
  597. MemBit2DelBits(
  598. IN OUT PM_BITMASK2 Bits,
  599. IN DWORD nBitsToDelete,
  600. IN BOOL fEnd
  601. )
  602. {
  603. ARRAY_LOCATION Loc;
  604. DWORD i;
  605. DWORD Size;
  606. DWORD Error;
  607. PM_BITMASK1 Bit1, Bit1x;
  608. AssertRet(Bits && nBitsToDelete && Bits->Size > nBitsToDelete, ERROR_INVALID_PARAMETER);
  609. if( fEnd ) {
  610. Error = MemArrayLastLoc(&Bits->Array, &Loc);
  611. } else {
  612. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  613. }
  614. Require(ERROR_SUCCESS == Error);
  615. while( nBitsToDelete ) {
  616. Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
  617. Require(ERROR_SUCCESS == Error);
  618. Size = MemBit1GetSize(Bit1);
  619. if( nBitsToDelete >= Size ) {
  620. nBitsToDelete -= Size;
  621. Bits->Size -= Size;
  622. Error = MemBit1Cleanup(Bit1);
  623. Require(ERROR_SUCCESS == Error);
  624. Error = MemArrayDelElement(&Bits->Array, &Loc, &Bit1x);
  625. Require(ERROR_SUCCESS == Error && Bit1x == Bit1);
  626. // Reset the ptr to the FIRST/LAST location to read the next element
  627. if( fEnd ) {
  628. Error = MemArrayLastLoc(&Bits->Array, &Loc);
  629. } else {
  630. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  631. }
  632. } else {
  633. Size -= nBitsToDelete;
  634. Bits->Size -= nBitsToDelete;
  635. nBitsToDelete = 0;
  636. Error = MemBit1DelBits(Bit1, Size, fEnd);
  637. }
  638. Require(ERROR_SUCCESS == Error);
  639. }
  640. Size = 0;
  641. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  642. while(ERROR_FILE_NOT_FOUND != Error ) {
  643. Require(ERROR_SUCCESS == Error);
  644. Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
  645. Require(ERROR_SUCCESS == Error && Bit1);
  646. Bit1->Offset = Size;
  647. Size += Bit1->Size;
  648. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  649. }
  650. MemArrayInitLoc( &Bits->Array, &Bits->Loc);
  651. return NO_ERROR;
  652. }
  653. DWORD _inline
  654. MemBit2AddBits(
  655. IN OUT PM_BITMASK2 Bits,
  656. IN DWORD nBitsToAdd,
  657. IN BOOL fEnd
  658. )
  659. {
  660. ARRAY_LOCATION Loc;
  661. DWORD i;
  662. DWORD Size;
  663. DWORD Error;
  664. PM_BITMASK1 Bit1;
  665. AssertRet(Bits && nBitsToAdd, ERROR_INVALID_PARAMETER);
  666. while( nBitsToAdd ) {
  667. Size = (nBitsToAdd > MaxBit1Size) ? MaxBit1Size : nBitsToAdd;
  668. nBitsToAdd -= Size;
  669. Error = MemBit1Init(&Bit1, Size);
  670. if( ERROR_SUCCESS != Error ) break;
  671. if( fEnd ) {
  672. Error = MemArrayAddElement(
  673. &Bits->Array,
  674. Bit1
  675. );
  676. } else {
  677. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  678. Require(ERROR_SUCCESS == Error);
  679. Error = MemArrayInsElement(
  680. &Bits->Array,
  681. &Loc,
  682. Bit1
  683. );
  684. }
  685. if( ERROR_SUCCESS != Error ) break;
  686. Bits->Size += Size;
  687. }
  688. Size = 0;
  689. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  690. while(ERROR_FILE_NOT_FOUND != Error) {
  691. Require(ERROR_SUCCESS == Error);
  692. Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
  693. Require(ERROR_SUCCESS == Error && Bit1);
  694. Bit1->Offset = Size;
  695. Size += Bit1->Size;
  696. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  697. }
  698. MemArrayInitLoc( &Bits->Array, &Bits->Loc);
  699. return NO_ERROR;
  700. }
  701. DWORD _inline
  702. MemBit2GetSomeClearedBit(
  703. IN OUT PM_BITMASK2 Bits,
  704. OUT LPDWORD Offset,
  705. IN BOOL fAcquire, // if we find one, do we Set it?
  706. IN DWORD StartAddress,
  707. IN PARRAY Exclusions
  708. )
  709. {
  710. ARRAY_LOCATION Loc;
  711. DWORD Size;
  712. DWORD Error;
  713. DWORD nBit1s;
  714. PM_BITMASK1 Bit1;
  715. AssertRet(Bits && Offset, ERROR_INVALID_PARAMETER);
  716. nBit1s = MemArraySize(&Bits->Array);
  717. while( nBit1s-- != 0 ) {
  718. Error = MemArrayGetElement(&Bits->Array, &Bits->Loc, (LPVOID *)&Bit1);
  719. Require(ERROR_SUCCESS == Error);
  720. Error = MemBit1GetSomeClearedBit(Bit1, &Size, fAcquire, StartAddress+Bit1->Offset, Exclusions);
  721. if( ERROR_SUCCESS == Error ) {
  722. *Offset = Bit1->Offset + Size;
  723. return ERROR_SUCCESS;
  724. }
  725. Error = MemArrayNextLoc(&Bits->Array, &Bits->Loc);
  726. if( ERROR_SUCCESS != Error ) {
  727. Error = MemArrayInitLoc(&Bits->Array, &Bits->Loc);
  728. Require( ERROR_SUCCESS == Error );
  729. }
  730. }
  731. return ERROR_FILE_NOT_FOUND;
  732. }
  733. //BeginExport(function)
  734. DWORD
  735. MemBitInit(
  736. OUT PM_BITMASK *Bits,
  737. IN DWORD nBits
  738. ) //EndExport(function)
  739. {
  740. AssertRet(Bits && nBits, ERROR_INVALID_PARAMETER);
  741. return MemBit2Init(Bits,nBits);
  742. }
  743. //BeginExport(function)
  744. DWORD
  745. MemBitCleanup(
  746. IN OUT PM_BITMASK Bits
  747. ) //EndExport(function)
  748. {
  749. AssertRet(Bits, ERROR_INVALID_PARAMETER);
  750. return MemBit2Cleanup(Bits);
  751. }
  752. //BeginExport(function)
  753. DWORD
  754. MemBitSetOrClearAll(
  755. IN OUT PM_BITMASK Bits,
  756. IN BOOL fSet
  757. ) //EndExport(function)
  758. {
  759. return MemBit2SetOrClearAll(Bits,fSet);
  760. }
  761. //BeginExport(function)
  762. DWORD
  763. MemBitSetOrClear(
  764. IN OUT PM_BITMASK Bits,
  765. IN DWORD Location,
  766. IN BOOL fSet,
  767. IN LPBOOL fOldState
  768. ) //EndExport(function)
  769. {
  770. return MemBit2SetOrClear(Bits,Location,fSet, fOldState);
  771. }
  772. //BeginExport(function)
  773. BOOL
  774. MemBitIsSet(
  775. IN OUT PM_BITMASK Bits,
  776. IN DWORD Location
  777. ) //EndExport(function)
  778. {
  779. BOOL Test;
  780. Test = MemBit2IsSet(Bits, Location);
  781. return Test;
  782. }
  783. //BeginExport(function)
  784. DWORD
  785. MemBitGetSize(
  786. IN PM_BITMASK Bits
  787. ) //EndExport(function)
  788. {
  789. return MemBit2GetSize(Bits);
  790. }
  791. //BeginExport(function)
  792. DWORD
  793. MemBitGetSetBitsInRange(
  794. IN PM_BITMASK Bits,
  795. IN DWORD dwFrom,
  796. IN DWORD dwTo
  797. ) //EndExport(function)
  798. {
  799. return MemBit2GetSetBitsInRange(Bits, dwFrom, dwTo);
  800. }
  801. //BeginExport(function)
  802. DWORD
  803. MemBitGetSetBitsSize(
  804. IN PM_BITMASK Bits
  805. ) //EndExport(function)
  806. {
  807. return MemBit2GetSetBitsSize(Bits);
  808. }
  809. //BeginExport(function)
  810. DWORD
  811. MemBitAddOrDelBits(
  812. IN OUT PM_BITMASK Bits,
  813. IN DWORD nBitsToAddOrDelete,
  814. IN BOOL fAdd,
  815. IN BOOL fEnd
  816. ) //EndExport(function)
  817. {
  818. if( fAdd ) return MemBit2AddBits(Bits, nBitsToAddOrDelete, fEnd);
  819. return MemBit2DelBits(Bits,nBitsToAddOrDelete, fEnd);
  820. }
  821. //BeginExport(function)
  822. DWORD
  823. MemBitGetSomeClearedBit(
  824. IN OUT PM_BITMASK Bits,
  825. OUT DWORD *Offset,
  826. IN BOOL fAcquire, // Acquire or just lookup?
  827. IN DWORD StartAddress,
  828. IN PARRAY Exclusions
  829. ) //EndExport(function)
  830. {
  831. return MemBit2GetSomeClearedBit(Bits,Offset,fAcquire, StartAddress, Exclusions);
  832. }
  833. //BeginExport(function)
  834. DWORD
  835. MemBitConvertToCluster(
  836. IN PM_BITMASK Bits,
  837. IN DWORD StartAddress,
  838. OUT LPBYTE *InUseClusters,
  839. OUT DWORD *InUseClustersSize,
  840. OUT LPBYTE *UsedClusters,
  841. OUT DWORD *UsedClustersSize
  842. ) //EndExport(function)
  843. {
  844. DWORD Error;
  845. DWORD Cluster;
  846. DWORD i, j;
  847. DWORD nBits;
  848. DWORD nBit1s;
  849. DWORD Size;
  850. DWORD UsedSize;
  851. DWORD InUseSize;
  852. LPDWORD Used;
  853. LPDWORD InUse;
  854. PM_BITMASK1 Bit1;
  855. ARRAY_LOCATION Loc;
  856. nBits = MemBitGetSize(Bits);
  857. if( 0 == nBits || 0 == MemBitGetSetBitsSize(Bits) ) {
  858. InUse = MemAlloc(sizeof(DWORD));
  859. Used = MemAlloc(sizeof(DWORD));
  860. if( NULL == InUse || NULL == Used ) {
  861. if( InUse ) MemFree(InUse);
  862. if( Used ) MemFree(Used);
  863. Require(FALSE);
  864. return ERROR_NOT_ENOUGH_MEMORY;
  865. }
  866. *Used = *InUse = 0;
  867. *InUseClusters = (LPBYTE)InUse;
  868. *UsedClusters = (LPBYTE)Used;
  869. *InUseClustersSize = *UsedClustersSize = sizeof(DWORD);
  870. return ERROR_SUCCESS;
  871. }
  872. nBit1s = MemArraySize(&Bits->Array);
  873. Require(nBit1s);
  874. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  875. UsedSize = InUseSize = 1; // no matter what, we always use a DWORD for total size
  876. for(i = 0; i < nBit1s ; i ++ ) {
  877. Require(ERROR_SUCCESS == Error);
  878. Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
  879. Require(ERROR_SUCCESS == Error && Bit1);
  880. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  881. // : Dont touch Bit1 directly like below? not really clean
  882. if( 0 == Bit1->nSet ) continue; // no bit is set, nothing to do..
  883. if( Bit1->Size == Bit1->nSet ) { // all bits set, nothing to do except for few odd bits
  884. UsedSize += Bit1->Size/32;
  885. if( Bit1->Size % 32 ) InUseSize+=2; // fill the odd bits in InUse so that we dont mark extra bits as used
  886. continue;
  887. }
  888. for( j = 0; j < Bit1->Size/32; j ++ ) {
  889. if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) {
  890. UsedSize ++; // this 32-bit is completely filled
  891. } else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) {
  892. InUseSize += 2; // this 32 bit is partially filled, not quite empty
  893. }
  894. }
  895. if( j * 32 < Bit1->Size ) InUseSize +=2; // for the last few bits..
  896. }
  897. InUse = MemAlloc(InUseSize * sizeof(DWORD));
  898. Used = MemAlloc(UsedSize * sizeof(DWORD));
  899. if( NULL == Used || NULL == InUse ) {
  900. if( InUse ) MemFree(InUse);
  901. if( Used ) MemFree(Used);
  902. return ERROR_NOT_ENOUGH_MEMORY;
  903. }
  904. *InUseClustersSize = sizeof(DWORD)*InUseSize; // fill in the sizes and ptrs to be returned..
  905. *InUseClusters = (LPBYTE)InUse;
  906. *UsedClusters = (LPBYTE)Used;
  907. *UsedClustersSize = sizeof(DWORD)*UsedSize;
  908. Error = MemArrayInitLoc(&Bits->Array, &Loc);
  909. UsedSize = InUseSize = 1;
  910. for(i = 0; i < nBit1s ; i ++ ) {
  911. Require(ERROR_SUCCESS == Error);
  912. Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
  913. Require(ERROR_SUCCESS == Error && Bit1);
  914. Error = MemArrayNextLoc(&Bits->Array, &Loc);
  915. // Dont touch Bit1 directly like below? not really clean
  916. if( 0 == Bit1->nSet ) { // all bits clear ==> just ignore
  917. StartAddress += Bit1->Size;
  918. continue;
  919. }
  920. if( Bit1->nSet == Bit1->Size ) { // handle all bits set here (loose bits need to be handled later)
  921. for( j = 0; j < Bit1->Size/32; j ++ ) {
  922. Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8;
  923. }
  924. } else {
  925. for( j = 0; j < Bit1->Size/32; j ++ ) {
  926. if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) {
  927. Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8;
  928. } else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) {
  929. #ifdef _X86_ // on X86, the first byte is the lowest order byte..
  930. Cluster = ((LPDWORD)(Bit1->Mask))[j];
  931. #else // it maynot be so on other machines, so combine the bytes manually..
  932. Cluster = Bit1->Mask[j*sizeof(DWORD)];
  933. Cluster |= (Bit1->Mask[j*sizeof(DWORD)+1]) << 8;
  934. Cluster |= (Bit1->Mask[j*sizeof(DWORD)+2]) << 16;
  935. Cluster |= (Bit1->Mask[j*sizeof(DWORD)+3]) << 24;
  936. #endif
  937. InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8;
  938. InUse[InUseSize++] = Cluster;
  939. }
  940. }
  941. }
  942. if( j * 32 < Bit1->Size ) { // copy the last few bits off..
  943. InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8;
  944. Cluster = 0;
  945. j *= 32;
  946. while( j < Bit1->Size ) {
  947. if( MemBit1IsSet(Bit1, j) ) Cluster |= (1 << (j%32));
  948. j ++;
  949. }
  950. InUse[InUseSize++] = Cluster;
  951. }
  952. StartAddress += Bit1->Size; // move the start address fwd for the next set..
  953. }
  954. InUse[0] = (InUseSize -1)/2; // size in header does not include itself
  955. Used[0] = UsedSize -1; // it is just the # of CLUSTERS..
  956. Require(InUseSize*sizeof(DWORD) == *InUseClustersSize);
  957. Require(UsedSize*sizeof(DWORD) == *UsedClustersSize);
  958. return ERROR_SUCCESS;
  959. }
  960. //================================================================================
  961. // End of file
  962. //================================================================================