3244{
3246 SIZE_T expect_size, diff, alloc_size, extra_size, tail_size = 0;
3247 unsigned char *ptr0, *ptr1, *ptr2,
tail;
3248 char tail_buf[64], padd_buf[64];
3249 void *tmp_ptr, **user_ptr;
3253
3256 {
3257 skip(
"skipping block tests\n" );
3258 return;
3259 }
3260
3261 if (!global_flags && !alloc_flags) extra_size = 8;
3262 else extra_size = 2 * sizeof(void *);
3264 if (heap_flags & padd_flags) extra_size += 2 * sizeof(void *);
3265
3267 memset( tail_buf, 0xab,
sizeof(tail_buf) );
3268 memset( padd_buf, 0,
sizeof(padd_buf) );
3269
3270 for (alloc_size = 0x20000 * sizeof(void *) - 0x3000; alloc_size > 0; alloc_size >>= 1)
3271 {
3273
3280
3282 ok( !(
align & (2 *
sizeof(
void *) - 1)),
"wrong align\n" );
3283
3284 expect_size =
max( alloc_size, 2 *
sizeof(
void *) );
3287 todo_wine_if( (!global_flags && alloc_size < 2 *
sizeof(
void *)) ||
3289#ifdef __REACTOS__
3291#endif
3292 ok( diff == expect_size,
"got diff %#Ix exp %#Ix\n", diff, expect_size );
3293 ok( !
memcmp( ptr0 + alloc_size, tail_buf, tail_size ),
"missing block tail\n" );
3294 ok( !
memcmp( ptr1 + alloc_size, tail_buf, tail_size ),
"missing block tail\n" );
3295 ok( !
memcmp( ptr2 + alloc_size, tail_buf, tail_size ),
"missing block tail\n" );
3296
3303
3305
3306 if (diff != expect_size)
3307 {
3310 break;
3311 }
3312 }
3313
3314
3315
3316
3317 alloc_size = 0x20000 * sizeof(void *) - 0x2000;
3319
3322 ok( !((
UINT_PTR)ptr0 & (2 *
sizeof(
void *) - 1)),
"got unexpected ptr align\n" );
3323
3324 ok( !
memcmp( ptr0 + alloc_size, tail_buf, tail_size ),
"missing block tail\n" );
3325
3328
3330
3331
3332 for (alloc_size = 0x20000 * sizeof(void *) - 0x1000; alloc_size < 0x800000; alloc_size <<= 1)
3333 {
3335
3338 ptr1 = pHeapAlloc(
heap, alloc_flags, alloc_size );
3340 ptr2 = pHeapAlloc(
heap, alloc_flags, alloc_size );
3342
3344 ok( !(
align & (8 *
sizeof(
void *) - 1)),
"wrong align\n" );
3345
3346 expect_size =
max( alloc_size, 2 *
sizeof(
void *) );
3350 ok( diff > expect_size, "got diff %
#Ix\n", diff );
3351
3352 tail = ptr0[alloc_size] | ptr1[alloc_size] | ptr2[alloc_size];
3353 ok( !tail, "got tail\n" );
3354
3355 ret = HeapFree( heap, 0, ptr2 );
3356 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3357 ret = HeapFree( heap, 0, ptr1 );
3358 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3359 ret = HeapFree( heap, 0, ptr0 );
3360 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3361 winetest_pop_context();
3362
3363 if (diff == expect_size || (align & (8 * sizeof(void *) - 1)) || tail)
3364 {
3365 todo_wine
3366 win_skip("skipping sizes\n");
3367 break;
3368 }
3369 }
3370
3371 /* Undocumented HEAP_ADD_USER_INFO flag can be used to force an additional padding
3372 * on small block sizes. Small block use it to store user info, larger blocks
3373 * store them in their block header instead.
3374 *
3375 * RtlGetUserInfoHeap also requires the flag to work consistently, and otherwise
3376 * causes crashes when heap flags are used, or on 32-bit.
3377 */
3378 if (!(heap_flags & padd_flags))
3379 {
3380 alloc_size = 0x1000;
3381 winetest_push_context( "size %#Ix", alloc_size );
3382 ptr0 = pHeapAlloc( heap, 0xc00|HEAP_ADD_USER_INFO, alloc_size );
3383 ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
3384 ptr1 = HeapAlloc( heap, 0x200|HEAP_ADD_USER_INFO, alloc_size );
3385 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
3386 ptr2 = HeapAlloc( heap, HEAP_ADD_USER_INFO, alloc_size );
3387 ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
3388
3389 expect_size = max( alloc_size, 2 * sizeof(void *) );
3390 expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size + 2 * sizeof(void *) );
3391 diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) );
3392 ok( diff == expect_size, "got diff %#Ix\n", diff );
3393
3394 ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3395 ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3396 ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3397
3398 ok( !memcmp( ptr0 + alloc_size + tail_size, padd_buf, 2 * sizeof(void *) ), "unexpected padding\n" );
3399
3400 tmp_ptr = (void *)0xdeadbeef;
3401 tmp_flags = 0xdeadbeef;
3402 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3403 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3404 ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr );
3405 ok( tmp_flags == 0xc00, "got flags %#lx\n", tmp_flags );
3406
3407 tmp_ptr = (void *)0xdeadbeef;
3408 tmp_flags = 0xdeadbeef;
3409 ret = pRtlGetUserInfoHeap( heap, 0, ptr1, (void **)&tmp_ptr, &tmp_flags );
3410 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3411 ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr );
3412 ok( tmp_flags == 0x200, "got flags %#lx\n", tmp_flags );
3413
3414 ret = pRtlSetUserValueHeap( heap, 0, ptr0, (void *)0xdeadbeef );
3415 ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
3416 SetLastError( 0xdeadbeef );
3417 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0, 0x1000 );
3418#ifdef __REACTOS__
3419 if (GetNTVersion() >= _WIN32_WINNT_VISTA)
3420#endif
3421 ok( !ret, "RtlSetUserFlagsHeap succeeded\n" );
3422#ifdef __REACTOS__
3423 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got error %lu\n", GetLastError() );
3424#else
3425 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
3426#endif
3427 SetLastError( 0xdeadbeef );
3428 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0x100, 0 );
3429#ifdef __REACTOS__
3430 if (GetNTVersion() >= _WIN32_WINNT_VISTA)
3431#endif
3432 ok( !ret, "RtlSetUserFlagsHeap succeeded\n" );
3433#ifdef __REACTOS__
3434 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got error %lu\n", GetLastError() );
3435#else
3436 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
3437#endif
3438 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0x400, 0x200 );
3439 ok( ret, "RtlSetUserFlagsHeap failed, error %lu\n", GetLastError() );
3440
3441 tmp_ptr = NULL;
3442 tmp_flags = 0;
3443 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3444 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3445 ok( tmp_ptr == (void *)0xdeadbeef, "got ptr %p\n", tmp_ptr );
3446 ok( tmp_flags == 0xa00 || broken(tmp_flags == 0xc00) /* w1064v1507 */,
3447 "got flags %#lx\n", tmp_flags );
3448
3449 user_ptr = (void **)(ptr0 + alloc_size + tail_size);
3450 ok( user_ptr[1] == (void *)0xdeadbeef, "unexpected user value\n" );
3451 user_ptr[0] = (void *)0xdeadbeef;
3452 user_ptr[1] = (void *)0xdeadbee0;
3453
3454 tmp_ptr = NULL;
3455 tmp_flags = 0;
3456 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3457 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3458 ok( tmp_ptr == (void *)0xdeadbee0, "got ptr %p\n", tmp_ptr );
3459 ok( tmp_flags == 0xa00 || broken(tmp_flags == 0xc00) /* w1064v1507 */,
3460 "got flags %#lx\n", tmp_flags );
3461
3462 ret = HeapFree( heap, 0, ptr2 );
3463 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3464 ret = HeapFree( heap, 0, ptr1 );
3465 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3466 ret = HeapFree( heap, 0, ptr0 );
3467 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3468 winetest_pop_context();
3469 }
3470}
struct outqueuenode * tail
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
_ACRTIMP __int64 __cdecl llabs(__int64)
int align(int length, int align)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
#define todo_wine_if(is_todo)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
#define ALIGN_BLOCK_SIZE(x)
#define _WIN32_WINNT_VISTA