1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for RtlReAllocateHeap
5  * PROGRAMMERS:     Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 static
11 BOOLEAN
12 CheckBuffer(
13     PVOID Buffer,
14     SIZE_T Size,
15     UCHAR Value)
16 {
17     PUCHAR Array = Buffer;
18     SIZE_T i;
19 
20     for (i = 0; i < Size; i++)
21         if (Array[i] != Value)
22         {
23             trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i);
24             return FALSE;
25         }
26     return TRUE;
27 }
28 
29 static
30 BOOLEAN
31 ReAllocBuffer(
32     PUCHAR *Buffer,
33     SIZE_T Size,
34     SIZE_T *OldSizePtr,
35     PCSTR Action)
36 {
37     PUCHAR NewBuffer;
38     SIZE_T OldSize = *OldSizePtr;
39 
40     RtlFillMemory(*Buffer, OldSize, 0x7a);
41     NewBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
42                                   HEAP_ZERO_MEMORY,
43                                   *Buffer,
44                                   Size);
45     if (!NewBuffer)
46     {
47         skip("RtlReAllocateHeap failed for size %lu (%s)\n", Size, Action);
48         return FALSE;
49     }
50     *Buffer = NewBuffer;
51     ok_hex(RtlSizeHeap(RtlGetProcessHeap(), 0, NewBuffer), Size);
52     if (OldSize < Size)
53     {
54         ok(CheckBuffer(NewBuffer, OldSize, 0x7a), "CheckBuffer failed at size 0x%lx -> 0x%lx\n", OldSize, Size);
55         ok(CheckBuffer(NewBuffer + OldSize, Size - OldSize, 0), "HEAP_ZERO_MEMORY not respected for 0x%lx -> 0x%lx\n", OldSize, Size);
56     }
57     else
58     {
59         ok(CheckBuffer(NewBuffer, Size, 0x7a), "CheckBuffer failed at size 0x%lx -> 0x%lx\n", OldSize, Size);
60     }
61     *OldSizePtr = Size;
62     return TRUE;
63 }
64 
65 START_TEST(RtlReAllocateHeap)
66 {
67     PUCHAR Buffer = NULL;
68     SIZE_T OldSize = 0;
69     SIZE_T Size;
70     BOOLEAN Continue = TRUE;
71     BOOLEAN Success;
72     PVOID UserValue;
73     ULONG UserFlags;
74     PVOID Buffer2;
75 
76     OldSize = 0x100;
77     Buffer = RtlReAllocateHeap(RtlGetProcessHeap(),
78                                HEAP_ZERO_MEMORY,
79                                NULL,
80                                OldSize);
81     ok(Buffer == NULL, "RtlReAllocateHeap succeeded for NULL\n");
82     if (Buffer)
83         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
84 
85     Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
86                              HEAP_ZERO_MEMORY,
87                              OldSize);
88     if (!Buffer)
89     {
90         skip("RtlAllocateHeap failed for size %lu\n", OldSize);
91         return;
92     }
93     ok(CheckBuffer(Buffer, OldSize, 0), "HEAP_ZERO_MEMORY not respected for 0x%lx\n", OldSize);
94 
95     for (Size = 0x78000; Size < 0x90000 && Continue; Size += 0x100)
96     {
97         Continue = ReAllocBuffer(&Buffer, Size, &OldSize, "growing");
98     }
99 
100     /* and back again */
101     for (Size -= 0x100; Size >= 0x78000 && Continue; Size -= 0x100)
102     {
103         Continue = ReAllocBuffer(&Buffer, Size, &OldSize, "shrinking");
104     }
105     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
106 
107     /* Now make sure user flags/values get preserved */
108     OldSize = 0x100;
109     Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
110                              HEAP_ZERO_MEMORY | HEAP_SETTABLE_USER_VALUE | HEAP_SETTABLE_USER_FLAG2,
111                              OldSize);
112     if (!Buffer)
113     {
114         skip("RtlAllocateHeap failed for size %lu\n", OldSize);
115         return;
116     }
117 
118     UserValue = InvalidPointer;
119     UserFlags = 0x55555555;
120     Success = RtlGetUserInfoHeap(RtlGetProcessHeap(),
121                                  0,
122                                  Buffer,
123                                  &UserValue,
124                                  &UserFlags);
125     ok(Success == TRUE, "RtlGetUserInfoHeap returned %u\n", Success);
126     ok(UserValue == NULL, "UserValue = %p\n", UserValue);
127     ok(UserFlags == HEAP_SETTABLE_USER_FLAG2, "UserFlags = %lx\n", UserFlags);
128 
129     Success = RtlSetUserFlagsHeap(RtlGetProcessHeap(),
130                                   0,
131                                   Buffer,
132                                   HEAP_SETTABLE_USER_FLAG1 | HEAP_SETTABLE_USER_FLAG2,
133                                   HEAP_SETTABLE_USER_FLAG3);
134     ok(Success == TRUE, "RtlSetUserFlagsHeap returned %u\n", Success);
135 
136     Success = RtlSetUserValueHeap(RtlGetProcessHeap(),
137                                   0,
138                                   Buffer,
139                                   &UserValue);
140     ok(Success == TRUE, "RtlSetUserValueHeap returned %u\n", Success);
141 
142     UserValue = InvalidPointer;
143     UserFlags = 0x55555555;
144     Success = RtlGetUserInfoHeap(RtlGetProcessHeap(),
145                                  0,
146                                  Buffer,
147                                  &UserValue,
148                                  &UserFlags);
149     ok(Success == TRUE, "RtlGetUserInfoHeap returned %u\n", Success);
150     ok(UserValue == &UserValue, "UserValue = %p, expected %p\n", UserValue, &UserValue);
151     ok(UserFlags == HEAP_SETTABLE_USER_FLAG3, "UserFlags = %lx\n", UserFlags);
152 
153     /* shrink (preserves flags) */
154     Buffer2 = RtlReAllocateHeap(RtlGetProcessHeap(),
155                                 HEAP_REALLOC_IN_PLACE_ONLY | HEAP_SETTABLE_USER_FLAG2,
156                                 Buffer,
157                                 OldSize / 2);
158     ok(Buffer2 == Buffer, "New Buffer is %p, expected %p\n", Buffer2, Buffer);
159     if (Buffer2) Buffer = Buffer2;
160     UserValue = InvalidPointer;
161     UserFlags = 0x55555555;
162     Success = RtlGetUserInfoHeap(RtlGetProcessHeap(),
163                                  0,
164                                  Buffer,
165                                  &UserValue,
166                                  &UserFlags);
167     ok(Success == TRUE, "RtlGetUserInfoHeap returned %u\n", Success);
168     ok(UserValue == &UserValue, "UserValue = %p, expected %p\n", UserValue, &UserValue);
169     ok(UserFlags == HEAP_SETTABLE_USER_FLAG3, "UserFlags = %lx\n", UserFlags);
170 
171     /* grow (overwrites flags) */
172     Buffer2 = RtlReAllocateHeap(RtlGetProcessHeap(),
173                                 HEAP_REALLOC_IN_PLACE_ONLY | HEAP_SETTABLE_USER_FLAG1,
174                                 Buffer,
175                                 OldSize / 4 * 3);
176     ok(Buffer2 == Buffer, "New Buffer is %p, expected %p\n", Buffer2, Buffer);
177     if (Buffer2) Buffer = Buffer2;
178     UserValue = InvalidPointer;
179     UserFlags = 0x55555555;
180     Success = RtlGetUserInfoHeap(RtlGetProcessHeap(),
181                                  0,
182                                  Buffer,
183                                  &UserValue,
184                                  &UserFlags);
185     ok(Success == TRUE, "RtlGetUserInfoHeap returned %u\n", Success);
186     ok(UserValue == &UserValue, "UserValue = %p, expected %p\n", UserValue, &UserValue);
187     ok(UserFlags == HEAP_SETTABLE_USER_FLAG1, "UserFlags = %lx\n", UserFlags);
188 
189     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
190 }
191