1 /* Unit test suite for Rtl bitmap functions
2  *
3  * Copyright 2002 Jon Griffiths
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  * NOTES
20  * We use function pointers here as some of the bitmap functions exist only
21  * in later versions of ntdll.
22  */
23 
24 #include "ntdll_test.h"
25 
26 #ifdef __WINE_WINTERNL_H
27 
28 /* Function ptrs for ordinal calls */
29 static HMODULE hntdll = 0;
30 static VOID (WINAPI *pRtlInitializeBitMap)(PRTL_BITMAP,LPBYTE,ULONG);
31 static VOID (WINAPI *pRtlSetAllBits)(PRTL_BITMAP);
32 static VOID (WINAPI *pRtlClearAllBits)(PRTL_BITMAP);
33 static VOID (WINAPI *pRtlSetBits)(PRTL_BITMAP,ULONG,ULONG);
34 static VOID (WINAPI *pRtlClearBits)(PRTL_BITMAP,ULONG,ULONG);
35 static BOOLEAN (WINAPI *pRtlAreBitsSet)(PRTL_BITMAP,ULONG,ULONG);
36 static BOOLEAN (WINAPI *pRtlAreBitsClear)(PRTL_BITMAP,ULONG,ULONG);
37 static ULONG (WINAPI *pRtlFindSetBitsAndClear)(PRTL_BITMAP,ULONG,ULONG);
38 static ULONG (WINAPI *pRtlFindClearBitsAndSet)(PRTL_BITMAP,ULONG,ULONG);
39 static CCHAR (WINAPI *pRtlFindMostSignificantBit)(ULONGLONG);
40 static CCHAR (WINAPI *pRtlFindLeastSignificantBit)(ULONGLONG);
41 static ULONG (WINAPI *pRtlFindSetRuns)(PRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
42 static ULONG (WINAPI *pRtlFindClearRuns)(PRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
43 static ULONG (WINAPI *pRtlNumberOfSetBits)(PRTL_BITMAP);
44 static ULONG (WINAPI *pRtlNumberOfClearBits)(PRTL_BITMAP);
45 static ULONG (WINAPI *pRtlFindLongestRunSet)(PRTL_BITMAP,PULONG);
46 static ULONG (WINAPI *pRtlFindLongestRunClear)(PRTL_BITMAP,PULONG);
47 
48 static BYTE buff[256];
49 static RTL_BITMAP bm;
50 
51 static void InitFunctionPtrs(void)
52 {
53   hntdll = LoadLibraryA("ntdll.dll");
54   ok(hntdll != 0, "LoadLibrary failed\n");
55   if (hntdll)
56   {
57     pRtlInitializeBitMap = (void *)GetProcAddress(hntdll, "RtlInitializeBitMap");
58     pRtlSetAllBits = (void *)GetProcAddress(hntdll, "RtlSetAllBits");
59     pRtlClearAllBits = (void *)GetProcAddress(hntdll, "RtlClearAllBits");
60     pRtlSetBits = (void *)GetProcAddress(hntdll, "RtlSetBits");
61     pRtlClearBits = (void *)GetProcAddress(hntdll, "RtlClearBits");
62     pRtlAreBitsSet = (void *)GetProcAddress(hntdll, "RtlAreBitsSet");
63     pRtlAreBitsClear = (void *)GetProcAddress(hntdll, "RtlAreBitsClear");
64     pRtlNumberOfSetBits = (void *)GetProcAddress(hntdll, "RtlNumberOfSetBits");
65     pRtlNumberOfClearBits = (void *)GetProcAddress(hntdll, "RtlNumberOfClearBits");
66     pRtlFindSetBitsAndClear = (void *)GetProcAddress(hntdll, "RtlFindSetBitsAndClear");
67     pRtlFindClearBitsAndSet = (void *)GetProcAddress(hntdll, "RtlFindClearBitsAndSet");
68     pRtlFindMostSignificantBit = (void *)GetProcAddress(hntdll, "RtlFindMostSignificantBit");
69     pRtlFindLeastSignificantBit = (void *)GetProcAddress(hntdll, "RtlFindLeastSignificantBit");
70     pRtlFindSetRuns = (void *)GetProcAddress(hntdll, "RtlFindSetRuns");
71     pRtlFindClearRuns = (void *)GetProcAddress(hntdll, "RtlFindClearRuns");
72     pRtlFindLongestRunSet = (void *)GetProcAddress(hntdll, "RtlFindLongestRunSet");
73     pRtlFindLongestRunClear = (void *)GetProcAddress(hntdll, "RtlFindLongestRunClear");
74   }
75 }
76 
77 static void test_RtlInitializeBitMap(void)
78 {
79   bm.SizeOfBitMap = 0;
80   bm.Buffer = 0;
81 
82   memset(buff, 0, sizeof(buff));
83   buff[0] = 77; /* Check buffer is not written to during init */
84   buff[79] = 77;
85 
86   pRtlInitializeBitMap(&bm, buff, 800);
87   ok(bm.SizeOfBitMap == 800, "size uninitialised\n");
88   ok(bm.Buffer == (PULONG)buff,"buffer uninitialised\n");
89   ok(buff[0] == 77 && buff[79] == 77, "wrote to buffer\n");
90 }
91 
92 static void test_RtlSetAllBits(void)
93 {
94   if (!pRtlSetAllBits)
95     return;
96 
97   memset(buff, 0 , sizeof(buff));
98   pRtlInitializeBitMap(&bm, buff, 1);
99 
100   pRtlSetAllBits(&bm);
101   ok(buff[0] == 0xff && buff[1] == 0xff && buff[2] == 0xff &&
102      buff[3] == 0xff, "didn't round up size\n");
103   ok(buff[4] == 0, "set more than rounded size\n");
104 }
105 
106 static void test_RtlClearAllBits(void)
107 {
108   if (!pRtlClearAllBits)
109     return;
110 
111   memset(buff, 0xff , sizeof(buff));
112   pRtlInitializeBitMap(&bm, buff, 1);
113 
114   pRtlClearAllBits(&bm);
115   ok(!buff[0] && !buff[1] && !buff[2] && !buff[3], "didn't round up size\n");
116   ok(buff[4] == 0xff, "cleared more than rounded size\n");
117 }
118 
119 static void test_RtlSetBits(void)
120 {
121   if (!pRtlSetBits)
122     return;
123 
124   memset(buff, 0 , sizeof(buff));
125   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
126 
127   pRtlSetBits(&bm, 0, 1);
128   ok(buff[0] == 1, "didn't set 1st bit\n");
129 
130   buff[0] = 0;
131   pRtlSetBits(&bm, 7, 2);
132   ok(buff[0] == 0x80 && buff[1] == 1, "didn't span w/len < 8\n");
133 
134   buff[0] = buff[1] = 0;
135   pRtlSetBits(&bm, 7, 10);
136   ok(buff[0] == 0x80 && buff[1] == 0xff && buff[2] == 1, "didn't span w/len > 8\n");
137 
138   buff[0] = buff[1] = buff[2] = 0;
139   pRtlSetBits(&bm, 0, 8); /* 1st byte */
140   ok(buff[0] == 0xff, "didn't set all bits\n");
141   ok(!buff[1], "set too many bits\n");
142 
143   pRtlSetBits(&bm, sizeof(buff)*8-1, 1); /* last bit */
144   ok(buff[sizeof(buff)-1] == 0x80, "didn't set last bit\n");
145 }
146 
147 static void test_RtlClearBits(void)
148 {
149   if (!pRtlClearBits)
150     return;
151 
152   memset(buff, 0xff , sizeof(buff));
153   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
154 
155   pRtlClearBits(&bm, 0, 1);
156   ok(buff[0] == 0xfe, "didn't clear 1st bit\n");
157 
158   buff[0] = 0xff;
159   pRtlClearBits(&bm, 7, 2);
160   ok(buff[0] == 0x7f && buff[1] == 0xfe, "didn't span w/len < 8\n");
161 
162   buff[0] = buff[1] = 0xff;
163   pRtlClearBits(&bm, 7, 10);
164   ok(buff[0] == 0x7f && buff[1] == 0 && buff[2] == 0xfe, "didn't span w/len > 8\n");
165 
166   buff[0] = buff[1] = buff[2] = 0xff;
167   pRtlClearBits(&bm, 0, 8);  /* 1st byte */
168   ok(!buff[0], "didn't clear all bits\n");
169   ok(buff[1] == 0xff, "cleared too many bits\n");
170 
171   pRtlClearBits(&bm, sizeof(buff)*8-1, 1);
172   ok(buff[sizeof(buff)-1] == 0x7f, "didn't set last bit\n");
173 }
174 
175 static void test_RtlCheckBit(void)
176 {
177   BOOLEAN bRet;
178 
179   memset(buff, 0 , sizeof(buff));
180   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
181   pRtlSetBits(&bm, 0, 1);
182   pRtlSetBits(&bm, 7, 2);
183   pRtlSetBits(&bm, sizeof(buff)*8-1, 1);
184 
185   bRet = RtlCheckBit(&bm, 0);
186   ok (bRet, "didn't find set bit\n");
187   bRet = RtlCheckBit(&bm, 7);
188   ok (bRet, "didn't find set bit\n");
189   bRet = RtlCheckBit(&bm, 8);
190   ok (bRet, "didn't find set bit\n");
191   bRet = RtlCheckBit(&bm, sizeof(buff)*8-1);
192   ok (bRet, "didn't find set bit\n");
193   bRet = RtlCheckBit(&bm, 1);
194   ok (!bRet, "found non set bit\n");
195   bRet = RtlCheckBit(&bm, sizeof(buff)*8-2);
196   ok (!bRet, "found non set bit\n");
197 }
198 
199 static void test_RtlAreBitsSet(void)
200 {
201   BOOLEAN bRet;
202 
203   if (!pRtlAreBitsSet)
204     return;
205 
206   memset(buff, 0 , sizeof(buff));
207   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
208 
209   bRet = pRtlAreBitsSet(&bm, 0, 1);
210   ok (!bRet, "found set bits after init\n");
211 
212   pRtlSetBits(&bm, 0, 1);
213   bRet = pRtlAreBitsSet(&bm, 0, 1);
214   ok (bRet, "didn't find set bits\n");
215 
216   buff[0] = 0;
217   pRtlSetBits(&bm, 7, 2);
218   bRet = pRtlAreBitsSet(&bm, 7, 2);
219   ok(bRet, "didn't find w/len < 8\n");
220   bRet = pRtlAreBitsSet(&bm, 6, 3);
221   ok(!bRet, "found non set bit\n");
222   bRet = pRtlAreBitsSet(&bm, 7, 3);
223   ok(!bRet, "found non set bit\n");
224 
225   buff[0] = buff[1] = 0;
226   pRtlSetBits(&bm, 7, 10);
227   bRet = pRtlAreBitsSet(&bm, 7, 10);
228   ok(bRet, "didn't find w/len < 8\n");
229   bRet = pRtlAreBitsSet(&bm, 6, 11);
230   ok(!bRet, "found non set bit\n");
231   bRet = pRtlAreBitsSet(&bm, 7, 11);
232   ok(!bRet, "found non set bit\n");
233 
234   buff[0] = buff[1] = buff[2] = 0;
235   pRtlSetBits(&bm, 0, 8); /* 1st byte */
236   bRet = pRtlAreBitsSet(&bm, 0, 8);
237   ok(bRet, "didn't find whole byte\n");
238 
239   pRtlSetBits(&bm, sizeof(buff)*8-1, 1);
240   bRet = pRtlAreBitsSet(&bm, sizeof(buff)*8-1, 1);
241   ok(bRet, "didn't find last bit\n");
242 }
243 
244 static void test_RtlAreBitsClear(void)
245 {
246   BOOLEAN bRet;
247 
248   if (!pRtlAreBitsClear)
249     return;
250 
251   memset(buff, 0xff , sizeof(buff));
252   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
253 
254   bRet = pRtlAreBitsClear(&bm, 0, 1);
255   ok (!bRet, "found clear bits after init\n");
256 
257   pRtlClearBits(&bm, 0, 1);
258   bRet = pRtlAreBitsClear(&bm, 0, 1);
259   ok (bRet, "didn't find set bits\n");
260 
261   buff[0] = 0xff;
262   pRtlClearBits(&bm, 7, 2);
263   bRet = pRtlAreBitsClear(&bm, 7, 2);
264   ok(bRet, "didn't find w/len < 8\n");
265   bRet = pRtlAreBitsClear(&bm, 6, 3);
266   ok(!bRet, "found non clear bit\n");
267   bRet = pRtlAreBitsClear(&bm, 7, 3);
268   ok(!bRet, "found non clear bit\n");
269 
270   buff[0] = buff[1] = 0xff;
271   pRtlClearBits(&bm, 7, 10);
272   bRet = pRtlAreBitsClear(&bm, 7, 10);
273   ok(bRet, "didn't find w/len < 8\n");
274   bRet = pRtlAreBitsClear(&bm, 6, 11);
275   ok(!bRet, "found non clear bit\n");
276   bRet = pRtlAreBitsClear(&bm, 7, 11);
277   ok(!bRet, "found non clear bit\n");
278 
279   buff[0] = buff[1] = buff[2] = 0xff;
280   pRtlClearBits(&bm, 0, 8); /* 1st byte */
281   bRet = pRtlAreBitsClear(&bm, 0, 8);
282   ok(bRet, "didn't find whole byte\n");
283 
284   pRtlClearBits(&bm, sizeof(buff)*8-1, 1);
285   bRet = pRtlAreBitsClear(&bm, sizeof(buff)*8-1, 1);
286   ok(bRet, "didn't find last bit\n");
287 }
288 
289 static void test_RtlNumberOfSetBits(void)
290 {
291   ULONG ulCount;
292 
293   if (!pRtlNumberOfSetBits)
294     return;
295 
296   memset(buff, 0 , sizeof(buff));
297   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
298 
299   ulCount = pRtlNumberOfSetBits(&bm);
300   ok(ulCount == 0, "set bits after init\n");
301 
302   pRtlSetBits(&bm, 0, 1); /* Set 1st bit */
303   ulCount = pRtlNumberOfSetBits(&bm);
304   ok(ulCount == 1, "count wrong\n");
305 
306   pRtlSetBits(&bm, 7, 8); /* 8 more, spanning bytes 1-2 */
307   ulCount = pRtlNumberOfSetBits(&bm);
308   ok(ulCount == 8+1, "count wrong\n");
309 
310   pRtlSetBits(&bm, 17, 33); /* 33 more crossing ULONG boundary */
311   ulCount = pRtlNumberOfSetBits(&bm);
312   ok(ulCount == 8+1+33, "count wrong\n");
313 
314   pRtlSetBits(&bm, sizeof(buff)*8-1, 1); /* Set last bit */
315   ulCount = pRtlNumberOfSetBits(&bm);
316   ok(ulCount == 8+1+33+1, "count wrong\n");
317 }
318 
319 static void test_RtlNumberOfClearBits(void)
320 {
321   ULONG ulCount;
322 
323   if (!pRtlNumberOfClearBits)
324     return;
325 
326   memset(buff, 0xff , sizeof(buff));
327   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
328 
329   ulCount = pRtlNumberOfClearBits(&bm);
330   ok(ulCount == 0, "cleared bits after init\n");
331 
332   pRtlClearBits(&bm, 0, 1); /* Set 1st bit */
333   ulCount = pRtlNumberOfClearBits(&bm);
334   ok(ulCount == 1, "count wrong\n");
335 
336   pRtlClearBits(&bm, 7, 8); /* 8 more, spanning bytes 1-2 */
337   ulCount = pRtlNumberOfClearBits(&bm);
338   ok(ulCount == 8+1, "count wrong\n");
339 
340   pRtlClearBits(&bm, 17, 33); /* 33 more crossing ULONG boundary */
341   ulCount = pRtlNumberOfClearBits(&bm);
342   ok(ulCount == 8+1+33, "count wrong\n");
343 
344   pRtlClearBits(&bm, sizeof(buff)*8-1, 1); /* Set last bit */
345   ulCount = pRtlNumberOfClearBits(&bm);
346   ok(ulCount == 8+1+33+1, "count wrong\n");
347 }
348 
349 /* Note: this tests RtlFindSetBits also */
350 static void test_RtlFindSetBitsAndClear(void)
351 {
352   BOOLEAN bRet;
353   ULONG ulPos;
354 
355   if (!pRtlFindSetBitsAndClear)
356     return;
357 
358   memset(buff, 0, sizeof(buff));
359   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
360 
361   pRtlSetBits(&bm, 0, 32);
362   ulPos = pRtlFindSetBitsAndClear(&bm, 32, 0);
363   ok (ulPos == 0, "didn't find bits\n");
364   if(ulPos == 0)
365   {
366     bRet = pRtlAreBitsClear(&bm, 0, 32);
367     ok (bRet, "found but didn't clear\n");
368   }
369 
370   memset(buff, 0 , sizeof(buff));
371   pRtlSetBits(&bm, 40, 77);
372   ulPos = pRtlFindSetBitsAndClear(&bm, 77, 0);
373   ok (ulPos == 40, "didn't find bits\n");
374   if(ulPos == 40)
375   {
376     bRet = pRtlAreBitsClear(&bm, 40, 77);
377     ok (bRet, "found but didn't clear\n");
378   }
379 }
380 
381 /* Note: this tests RtlFindClearBits also */
382 static void test_RtlFindClearBitsAndSet(void)
383 {
384   BOOLEAN bRet;
385   ULONG ulPos;
386 
387   if (!pRtlFindClearBitsAndSet)
388     return;
389 
390   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
391 
392   memset(buff, 0xff, sizeof(buff));
393   pRtlSetBits(&bm, 0, 32);
394   ulPos = pRtlFindSetBitsAndClear(&bm, 32, 0);
395   ok (ulPos == 0, "didn't find bits\n");
396   if(ulPos == 0)
397   {
398       bRet = pRtlAreBitsClear(&bm, 0, 32);
399       ok (bRet, "found but didn't clear\n");
400   }
401 
402   memset(buff, 0xff , sizeof(buff));
403   pRtlClearBits(&bm, 40, 77);
404   ulPos = pRtlFindClearBitsAndSet(&bm, 77, 50);
405   ok (ulPos == 40, "didn't find bits\n");
406   if(ulPos == 40)
407   {
408     bRet = pRtlAreBitsSet(&bm, 40, 77);
409     ok (bRet, "found but didn't set\n");
410   }
411 }
412 
413 static void test_RtlFindMostSignificantBit(void)
414 {
415   int i;
416   signed char cPos;
417   ULONGLONG ulLong;
418 
419   if (!pRtlFindMostSignificantBit)
420     return;
421 
422   for (i = 0; i < 64; i++)
423   {
424     ulLong = 1ul;
425     ulLong <<= i;
426 
427     cPos = pRtlFindMostSignificantBit(ulLong);
428     ok (cPos == i, "didn't find MSB 0x%s %d %d\n",
429         wine_dbgstr_longlong(ulLong ), i, cPos);
430 
431     /* Set all bits lower than bit i */
432     ulLong = ((ulLong - 1) << 1) | 1;
433 
434     cPos = pRtlFindMostSignificantBit(ulLong);
435     ok (cPos == i, "didn't find MSB 0x%s %d %d\n",
436         wine_dbgstr_longlong(ulLong ), i, cPos);
437   }
438   cPos = pRtlFindMostSignificantBit(0);
439   ok (cPos == -1, "found bit when not set\n");
440 }
441 
442 static void test_RtlFindLeastSignificantBit(void)
443 {
444   int i;
445   signed char cPos;
446   ULONGLONG ulLong;
447 
448   if (!pRtlFindLeastSignificantBit)
449     return;
450 
451   for (i = 0; i < 64; i++)
452   {
453     ulLong = (ULONGLONG)1 << i;
454 
455     cPos = pRtlFindLeastSignificantBit(ulLong);
456     ok (cPos == i, "didn't find LSB 0x%s %d %d\n",
457         wine_dbgstr_longlong(ulLong ), i, cPos);
458 
459     ulLong = ~((ULONGLONG)0) << i;
460 
461     cPos = pRtlFindLeastSignificantBit(ulLong);
462     ok (cPos == i, "didn't find LSB 0x%s %d %d\n",
463         wine_dbgstr_longlong(ulLong ), i, cPos);
464   }
465   cPos = pRtlFindLeastSignificantBit(0);
466   ok (cPos == -1, "found bit when not set\n");
467 }
468 
469 /* Note: Also tests RtlFindLongestRunSet() */
470 static void test_RtlFindSetRuns(void)
471 {
472   RTL_BITMAP_RUN runs[16];
473   ULONG ulCount;
474 
475   if (!pRtlFindSetRuns)
476     return;
477 
478   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
479 
480   memset(buff, 0, sizeof(buff));
481   ulCount = pRtlFindSetRuns(&bm, runs, 16, TRUE);
482   ok (ulCount == 0, "found set bits in empty bitmap\n");
483 
484   memset(runs, 0, sizeof(runs));
485   memset(buff, 0xff, sizeof(buff));
486   ulCount = pRtlFindSetRuns(&bm, runs, 16, TRUE);
487   ok (ulCount == 1, "didn't find set bits\n");
488   ok (runs[0].StartingIndex == 0,"bad start\n");
489   ok (runs[0].NumberOfBits == sizeof(buff)*8,"bad size\n");
490 
491   /* Set up 3 runs */
492   memset(runs, 0, sizeof(runs));
493   memset(buff, 0, sizeof(buff));
494   pRtlSetBits(&bm, 7, 19);
495   pRtlSetBits(&bm, 101, 3);
496   pRtlSetBits(&bm, 1877, 33);
497 
498   /* Get first 2 */
499   ulCount = pRtlFindSetRuns(&bm, runs, 2, FALSE);
500   ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
501   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
502   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
503   ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
504   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
505   ok (runs[2].StartingIndex == 0,"found extra run\n");
506 
507   /* Get longest 3 */
508   memset(runs, 0, sizeof(runs));
509   ulCount = pRtlFindSetRuns(&bm, runs, 2, TRUE);
510   ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
511   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
512   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
513   ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
514   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
515   ok (runs[2].StartingIndex == 0,"found extra run\n");
516 
517   /* Get all 3 */
518   memset(runs, 0, sizeof(runs));
519   ulCount = pRtlFindSetRuns(&bm, runs, 3, TRUE);
520   ok(ulCount == 3, "RtlFindClearRuns returned %d, expected 3\n", ulCount);
521   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
522       runs[0].StartingIndex == 1877,"bad find\n");
523   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
524       runs[1].StartingIndex == 1877,"bad find\n");
525   ok (runs[2].StartingIndex == 7 || runs[2].StartingIndex == 101 ||
526       runs[2].StartingIndex == 1877,"bad find\n");
527   ok (runs[0].NumberOfBits + runs[1].NumberOfBits
528       + runs[2].NumberOfBits == 19 + 3 + 33,"bad size\n");
529   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
530   ok (runs[1].StartingIndex != runs[2].StartingIndex,"found run twice\n");
531   ok (runs[3].StartingIndex == 0,"found extra run\n");
532 
533   if (pRtlFindLongestRunSet)
534   {
535     ULONG ulStart = 0;
536 
537     ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
538     ok(ulCount == 33 && ulStart == 1877,"didn't find longest %d %d\n",ulCount,ulStart);
539 
540     memset(buff, 0, sizeof(buff));
541     ulCount = pRtlFindLongestRunSet(&bm, &ulStart);
542     ok(ulCount == 0,"found longest when none set\n");
543   }
544 }
545 
546 /* Note: Also tests RtlFindLongestRunClear() */
547 static void test_RtlFindClearRuns(void)
548 {
549   RTL_BITMAP_RUN runs[16];
550   ULONG ulCount;
551 
552   if (!pRtlFindClearRuns)
553     return;
554 
555   pRtlInitializeBitMap(&bm, buff, sizeof(buff)*8);
556 
557   memset(buff, 0xff, sizeof(buff));
558   ulCount = pRtlFindClearRuns(&bm, runs, 16, TRUE);
559   ok (ulCount == 0, "found clear bits in full bitmap\n");
560 
561   memset(runs, 0, sizeof(runs));
562   memset(buff, 0, sizeof(buff));
563   ulCount = pRtlFindClearRuns(&bm, runs, 16, TRUE);
564   ok (ulCount == 1, "didn't find clear bits\n");
565   ok (runs[0].StartingIndex == 0,"bad start\n");
566   ok (runs[0].NumberOfBits == sizeof(buff)*8,"bad size\n");
567 
568   /* Set up 3 runs */
569   memset(runs, 0, sizeof(runs));
570   memset(buff, 0xff, sizeof(buff));
571   pRtlClearBits(&bm, 7, 19);
572   pRtlClearBits(&bm, 101, 3);
573   pRtlClearBits(&bm, 1877, 33);
574 
575   /* Get first 2 */
576   ulCount = pRtlFindClearRuns(&bm, runs, 2, FALSE);
577   ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
578   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
579   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
580   ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
581   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
582   ok (runs[2].StartingIndex == 0,"found extra run\n");
583 
584   /* Get longest 3 */
585   memset(runs, 0, sizeof(runs));
586   ulCount = pRtlFindClearRuns(&bm, runs, 2, TRUE);
587   ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
588   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
589   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
590   ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
591   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
592   ok (runs[2].StartingIndex == 0,"found extra run\n");
593 
594   /* Get all 3 */
595   memset(runs, 0, sizeof(runs));
596   ulCount = pRtlFindClearRuns(&bm, runs, 3, TRUE);
597   ok(ulCount == 3, "RtlFindClearRuns returned %d, expected 3\n", ulCount);
598   ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
599       runs[0].StartingIndex == 1877,"bad find\n");
600   ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
601       runs[1].StartingIndex == 1877,"bad find\n");
602   ok (runs[2].StartingIndex == 7 || runs[2].StartingIndex == 101 ||
603       runs[2].StartingIndex == 1877,"bad find\n");
604   ok (runs[0].NumberOfBits + runs[1].NumberOfBits
605       + runs[2].NumberOfBits == 19 + 3 + 33,"bad size\n");
606   ok (runs[0].StartingIndex != runs[1].StartingIndex,"found run twice\n");
607   ok (runs[1].StartingIndex != runs[2].StartingIndex,"found run twice\n");
608   ok (runs[3].StartingIndex == 0,"found extra run\n");
609 
610   if (pRtlFindLongestRunClear)
611   {
612     ULONG ulStart = 0;
613 
614     ulCount = pRtlFindLongestRunClear(&bm, &ulStart);
615     ok(ulCount == 33 && ulStart == 1877,"didn't find longest\n");
616 
617     memset(buff, 0xff, sizeof(buff));
618     ulCount = pRtlFindLongestRunClear(&bm, &ulStart);
619     ok(ulCount == 0,"found longest when none clear\n");
620   }
621 
622 }
623 #endif
624 
625 START_TEST(rtlbitmap)
626 {
627 #ifdef __WINE_WINTERNL_H
628   InitFunctionPtrs();
629 
630   if (pRtlInitializeBitMap)
631   {
632     test_RtlInitializeBitMap();
633     test_RtlSetAllBits();
634     test_RtlClearAllBits();
635     test_RtlSetBits();
636     test_RtlClearBits();
637     test_RtlCheckBit();
638     test_RtlAreBitsSet();
639     test_RtlAreBitsClear();
640     test_RtlNumberOfSetBits();
641     test_RtlNumberOfClearBits();
642     test_RtlFindSetBitsAndClear();
643     test_RtlFindClearBitsAndSet();
644     test_RtlFindMostSignificantBit();
645     test_RtlFindLeastSignificantBit();
646     test_RtlFindSetRuns();
647     test_RtlFindClearRuns();
648   }
649 #endif
650 }
651