Source code of Windows XP (NT5)
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.

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