1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Test for LdrEnumResources 5 * PROGRAMMER: Timo Kreuzer 6 */ 7 8 #include "precomp.h" 9 10 #include <pseh/pseh2.h> 11 12 typedef struct _TEST_RESOURCES 13 { 14 IMAGE_RESOURCE_DIRECTORY TypeDirectory; 15 IMAGE_RESOURCE_DIRECTORY_ENTRY TypeEntries[2]; 16 IMAGE_RESOURCE_DIRECTORY Name1Directory; 17 IMAGE_RESOURCE_DIRECTORY_ENTRY Name1Entries[2]; 18 IMAGE_RESOURCE_DIRECTORY Name2Directory; 19 IMAGE_RESOURCE_DIRECTORY_ENTRY Name2Entries[2]; 20 IMAGE_RESOURCE_DIRECTORY Lang1Directory; 21 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang1Entries[2]; 22 IMAGE_RESOURCE_DIRECTORY Lang2Directory; 23 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang2Entries[2]; 24 IMAGE_RESOURCE_DIRECTORY Lang3Directory; 25 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang3Entries[2]; 26 IMAGE_RESOURCE_DIRECTORY Lang4Directory; 27 IMAGE_RESOURCE_DIRECTORY_ENTRY Lang4Entries[2]; 28 IMAGE_RESOURCE_DATA_ENTRY DataEntries[8]; 29 IMAGE_RESOURCE_DIRECTORY_STRING Name1String; 30 ULONG StringIndex; 31 WCHAR StringBuffer[20]; 32 } TEST_RESOURCES, *PTEST_RESOURCES; 33 34 typedef struct _TEST_IMAGE 35 { 36 IMAGE_DOS_HEADER DosHeader; 37 IMAGE_NT_HEADERS NtHeaders; 38 IMAGE_SECTION_HEADER SectionHeaders[1]; 39 TEST_RESOURCES Resources; 40 } TEST_IMAGE, *PTEST_IMAGE; 41 42 static 43 VOID 44 InitializeResourceDirectory( 45 PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, 46 USHORT NumberOfNamedEntries, 47 USHORT NumberOfIdEntries) 48 { 49 ResourceDirectory->Characteristics = 0; 50 ResourceDirectory->TimeDateStamp = 0; 51 ResourceDirectory->MajorVersion = 0; 52 ResourceDirectory->MinorVersion = 0; 53 ResourceDirectory->NumberOfNamedEntries = NumberOfNamedEntries; 54 ResourceDirectory->NumberOfIdEntries = NumberOfIdEntries; 55 } 56 57 static 58 VOID 59 InitializeNamedEntry( 60 PTEST_RESOURCES Resource, 61 PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry, 62 PWCHAR Name, 63 PVOID Data) 64 { 65 DirEntry->Name = Resource->StringIndex * 2 + FIELD_OFFSET(TEST_RESOURCES, StringBuffer); 66 DirEntry->NameIsString = 1; 67 DirEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)Resource; 68 if (DirEntry < Resource->Lang1Entries) 69 DirEntry->DataIsDirectory = 1; 70 Resource->StringBuffer[Resource->StringIndex] = (USHORT)wcslen(Name); 71 wcscpy(&Resource->StringBuffer[Resource->StringIndex + 1], Name); 72 Resource->StringIndex += Resource->StringBuffer[Resource->StringIndex] * 2 + 1; 73 } 74 75 static 76 VOID 77 InitializeIdEntry( 78 PTEST_RESOURCES Resource, 79 PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry, 80 USHORT Id, 81 PVOID Data) 82 { 83 DirEntry->Name = Id; 84 DirEntry->NameIsString = 0; 85 DirEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)Resource; 86 if (DirEntry < Resource->Lang1Entries) 87 DirEntry->DataIsDirectory = 1; 88 } 89 90 static 91 VOID 92 InitializeDataEntry( 93 PVOID ImageBase, 94 PIMAGE_RESOURCE_DATA_ENTRY DataEntry, 95 PVOID Data, 96 ULONG Size) 97 { 98 99 DataEntry->OffsetToData = (PUCHAR)Data - (PUCHAR)ImageBase; 100 DataEntry->Size = Size; 101 DataEntry->CodePage = 0; 102 DataEntry->Reserved = 0; 103 } 104 105 static 106 VOID 107 InitializeTestResource( 108 PVOID ImageBase, 109 PTEST_RESOURCES Resource) 110 { 111 112 memset(Resource->StringBuffer, 0, sizeof(Resource->StringBuffer)); 113 Resource->StringIndex = 0; 114 115 InitializeResourceDirectory(&Resource->TypeDirectory, 0, 2); 116 InitializeIdEntry(Resource, &Resource->TypeEntries[0], 1, &Resource->Name1Directory); 117 InitializeIdEntry(Resource, &Resource->TypeEntries[1], 2, &Resource->Name2Directory); 118 119 InitializeResourceDirectory(&Resource->Name1Directory, 1, 1); 120 InitializeNamedEntry(Resource, &Resource->Name1Entries[0], L"TEST", &Resource->Lang1Directory); 121 InitializeIdEntry(Resource, &Resource->Name1Entries[1], 7, &Resource->Lang2Directory); 122 123 InitializeResourceDirectory(&Resource->Name2Directory, 2, 0); 124 InitializeNamedEntry(Resource, &Resource->Name2Entries[0], L"LOL", &Resource->Lang3Directory); 125 InitializeNamedEntry(Resource, &Resource->Name2Entries[1], L"xD", &Resource->Lang4Directory); 126 127 InitializeResourceDirectory(&Resource->Lang1Directory, 0, 2); 128 InitializeIdEntry(Resource, &Resource->Lang1Entries[0], 0x409, &Resource->DataEntries[0]); 129 InitializeIdEntry(Resource, &Resource->Lang1Entries[1], 0x407, &Resource->DataEntries[1]); 130 131 InitializeResourceDirectory(&Resource->Lang2Directory, 0, 2); 132 InitializeIdEntry(Resource, &Resource->Lang2Entries[0], 0x408, &Resource->DataEntries[2]); 133 InitializeIdEntry(Resource, &Resource->Lang2Entries[1], 0x406, &Resource->DataEntries[3]); 134 135 InitializeResourceDirectory(&Resource->Lang3Directory, 0, 2); 136 InitializeIdEntry(Resource, &Resource->Lang3Entries[0], 0x405, &Resource->DataEntries[4]); 137 InitializeIdEntry(Resource, &Resource->Lang3Entries[1], 0x403, &Resource->DataEntries[5]); 138 139 InitializeResourceDirectory(&Resource->Lang4Directory, 0, 2); 140 InitializeIdEntry(Resource, &Resource->Lang4Entries[0], 0x402, &Resource->DataEntries[6]); 141 InitializeIdEntry(Resource, &Resource->Lang4Entries[1], 0x404, &Resource->DataEntries[7]); 142 143 InitializeDataEntry(ImageBase, &Resource->DataEntries[0], Resource->StringBuffer + 0, 2); 144 InitializeDataEntry(ImageBase, &Resource->DataEntries[1], Resource->StringBuffer + 2, 4); 145 InitializeDataEntry(ImageBase, &Resource->DataEntries[2], Resource->StringBuffer + 4, 6); 146 InitializeDataEntry(ImageBase, &Resource->DataEntries[3], Resource->StringBuffer + 6, 8); 147 InitializeDataEntry(ImageBase, &Resource->DataEntries[4], Resource->StringBuffer + 8, 10); 148 InitializeDataEntry(ImageBase, &Resource->DataEntries[5], Resource->StringBuffer + 10, 12); 149 InitializeDataEntry(ImageBase, &Resource->DataEntries[6], Resource->StringBuffer + 12, 14); 150 InitializeDataEntry(ImageBase, &Resource->DataEntries[7], Resource->StringBuffer + 14, 16); 151 152 } 153 154 VOID 155 InitializeTestImage( 156 PTEST_IMAGE TestImage) 157 { 158 PIMAGE_DATA_DIRECTORY ResourceDirectory; 159 160 TestImage->DosHeader.e_magic = IMAGE_DOS_SIGNATURE; 161 TestImage->DosHeader.e_lfanew = sizeof(IMAGE_DOS_HEADER); 162 163 TestImage->NtHeaders.Signature = IMAGE_NT_SIGNATURE; 164 165 TestImage->NtHeaders.FileHeader.Machine = IMAGE_FILE_MACHINE_NATIVE; 166 TestImage->NtHeaders.FileHeader.NumberOfSections = 1; 167 TestImage->NtHeaders.FileHeader.TimeDateStamp = 0; 168 TestImage->NtHeaders.FileHeader.PointerToSymbolTable = 0; 169 TestImage->NtHeaders.FileHeader.NumberOfSymbols = 0; 170 TestImage->NtHeaders.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); 171 TestImage->NtHeaders.FileHeader.Characteristics = 0; 172 173 #ifdef _WIN64 174 TestImage->NtHeaders.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; 175 #else 176 TestImage->NtHeaders.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC; 177 #endif 178 TestImage->NtHeaders.OptionalHeader.ImageBase = (DWORD_PTR)TestImage; 179 TestImage->NtHeaders.OptionalHeader.SizeOfImage = sizeof(TEST_IMAGE); 180 TestImage->NtHeaders.OptionalHeader.SizeOfHeaders = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS); 181 TestImage->NtHeaders.OptionalHeader.NumberOfRvaAndSizes = ARRAYSIZE(TestImage->NtHeaders.OptionalHeader.DataDirectory); 182 183 ResourceDirectory = &TestImage->NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; 184 ResourceDirectory->VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources); 185 ResourceDirectory->Size = sizeof(TEST_RESOURCES); 186 187 strcpy((char*)TestImage->SectionHeaders[0].Name, ".rsrc"); 188 TestImage->SectionHeaders[0].Misc.VirtualSize = sizeof(TEST_IMAGE); 189 TestImage->SectionHeaders[0].VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources); 190 TestImage->SectionHeaders[0].SizeOfRawData = sizeof(TEST_IMAGE); 191 TestImage->SectionHeaders[0].PointerToRawData = FIELD_OFFSET(TEST_IMAGE, Resources); 192 TestImage->SectionHeaders[0].PointerToRelocations = 0; 193 TestImage->SectionHeaders[0].PointerToLinenumbers = 0; 194 TestImage->SectionHeaders[0].NumberOfRelocations = 0; 195 TestImage->SectionHeaders[0].NumberOfLinenumbers = 0; 196 TestImage->SectionHeaders[0].Characteristics = 0; 197 198 InitializeTestResource(TestImage, &TestImage->Resources); 199 } 200 201 #define ok_nwstr(str1, str2, count) \ 202 ok(wcsncmp((PWCHAR)str1, (PWCHAR)str2, count) == 0, \ 203 "string is wrong, expected: '%S', got '%S'\n", str1, str2); \ 204 205 #define ok_enumres(_Res, _Type, _Name, _Lang, _Data, _Size) \ 206 ok_dec((_Res)->Type, _Type); \ 207 if ((ULONG_PTR)(_Name) > 0xFFFF) \ 208 { \ 209 ok_size_t(*(WORD*)((_Res)->Name), wcslen((PWCHAR)(_Name))); \ 210 ok_nwstr((PWCHAR)((_Res)->Name + 2), (PWCHAR)_Name, *(WORD*)((_Res)->Name)); \ 211 } \ 212 else \ 213 { \ 214 ok_dec((_Res)->Name, (ULONG_PTR)_Name); \ 215 } \ 216 ok_hex((_Res)->Language, _Lang); \ 217 ok_ptr((PVOID)(_Res)->Data, _Data); \ 218 ok_dec((_Res)->Size, _Size); \ 219 ok_dec((_Res)->Reserved, 0); 220 221 static 222 void 223 Test_Data(PTEST_IMAGE TestImage) 224 { 225 LDR_RESOURCE_INFO ResourceInfo; 226 LDR_ENUM_RESOURCE_INFO EnumRes[8]; 227 ULONG ResourceCount; 228 NTSTATUS Status; 229 230 InitializeTestImage(TestImage); 231 232 memset(EnumRes, 0xcc, sizeof(EnumRes)); 233 234 ResourceInfo.Type = 1; 235 ResourceInfo.Name = 1; 236 ResourceInfo.Language = 0x408; 237 ResourceCount = 8; 238 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, EnumRes); 239 ok_hex(Status, STATUS_SUCCESS); 240 ok_dec(ResourceCount, 8); 241 242 ok_ptr((PVOID)EnumRes[0].Data, TestImage->Resources.StringBuffer); 243 ok_dec(EnumRes[0].Size, 2); 244 245 ok_enumres(&EnumRes[0], 1, L"TEST", 0x409, TestImage->Resources.StringBuffer, 2) 246 ok_enumres(&EnumRes[1], 1, L"TEST", 0x407, TestImage->Resources.StringBuffer + 2, 4) 247 ok_enumres(&EnumRes[2], 1, 7, 0x408, TestImage->Resources.StringBuffer + 4, 6) 248 ok_enumres(&EnumRes[3], 1, 7, 0x406, TestImage->Resources.StringBuffer + 6, 8) 249 ok_enumres(&EnumRes[4], 2, L"LOL", 0x405, TestImage->Resources.StringBuffer + 8, 10) 250 ok_enumres(&EnumRes[5], 2, L"LOL", 0x403, TestImage->Resources.StringBuffer + 10, 12) 251 ok_enumres(&EnumRes[6], 2, L"xD", 0x402, TestImage->Resources.StringBuffer + 12, 14) 252 ok_enumres(&EnumRes[7], 2, L"xD", 0x404, TestImage->Resources.StringBuffer + 14, 16) 253 254 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, EnumRes); 255 ok_hex(Status, STATUS_SUCCESS); 256 ok_dec(ResourceCount, 4); 257 258 } 259 260 261 static 262 void 263 Test_Parameters(PTEST_IMAGE TestImage) 264 { 265 LDR_RESOURCE_INFO ResourceInfo; 266 LDR_ENUM_RESOURCE_INFO Resources[8]; 267 ULONG ResourceCount; 268 NTSTATUS Status; 269 270 InitializeTestImage(TestImage); 271 272 ResourceInfo.Type = 6; 273 ResourceInfo.Name = 1; 274 ResourceInfo.Language = 0x409; 275 276 ResourceCount = 8; 277 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources); 278 ok_hex(Status, STATUS_SUCCESS); 279 ok_dec(ResourceCount, 0); 280 281 ResourceInfo.Type = 1; 282 ResourceInfo.Name = 7; 283 ResourceInfo.Language = 0x406; 284 ResourceCount = 8; 285 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 286 ok_hex(Status, STATUS_SUCCESS); 287 ok_dec(ResourceCount, 8); 288 289 ResourceCount = 8; 290 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, Resources); 291 ok_hex(Status, STATUS_SUCCESS); 292 ok_dec(ResourceCount, 4); 293 294 ResourceCount = 8; 295 Status = LdrEnumResources(TestImage, &ResourceInfo, 2, &ResourceCount, Resources); 296 ok_hex(Status, STATUS_SUCCESS); 297 ok_dec(ResourceCount, 2); 298 299 ResourceCount = 8; 300 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources); 301 ok_hex(Status, STATUS_SUCCESS); 302 ok_dec(ResourceCount, 1); 303 304 ResourceCount = 8; 305 Status = LdrEnumResources(TestImage, &ResourceInfo, 99, &ResourceCount, Resources); 306 ok_hex(Status, STATUS_SUCCESS); 307 ok_dec(ResourceCount, 1); 308 309 ResourceCount = 0; 310 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 311 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 312 ok_dec(ResourceCount, 8); 313 314 ResourceCount = 7; 315 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 316 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 317 ok_dec(ResourceCount, 8); 318 319 ResourceCount = 8; 320 Status = LdrEnumResources(NULL, &ResourceInfo, 1, &ResourceCount, Resources); 321 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND); 322 ok_dec(ResourceCount, 0); 323 324 ResourceCount = 8; 325 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL); 326 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 327 ok_dec(ResourceCount, 4); 328 329 ResourceCount = 8; 330 _SEH2_TRY 331 { 332 Status = LdrEnumResources(NULL, NULL, 0, NULL, NULL); 333 } 334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 335 { 336 Status = 0xDeadC0de; 337 } 338 _SEH2_END 339 ok_hex(Status, 0xDeadC0de); 340 341 ResourceCount = 42; 342 _SEH2_TRY 343 { 344 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, NULL, Resources); 345 } 346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 347 { 348 Status = 0xDeadC0de; 349 } 350 _SEH2_END 351 ok_hex(Status, 0xDeadC0de); 352 ok_dec(ResourceCount, 42); 353 354 ResourceCount = 8; 355 Status = LdrEnumResources(TestImage + 2, &ResourceInfo, 1, &ResourceCount, NULL); 356 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND); 357 ok_dec(ResourceCount, 0); 358 359 TestImage->Resources.TypeEntries[0].DataIsDirectory = 0; 360 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL); 361 ok_hex(Status, STATUS_INVALID_IMAGE_FORMAT); 362 ok_dec(ResourceCount, 0); 363 364 } 365 366 START_TEST(LdrEnumResources) 367 { 368 TEST_IMAGE TestImage; 369 RtlZeroMemory(&TestImage, sizeof(TestImage)); 370 371 Test_Parameters(&TestImage); 372 Test_Data(&TestImage); 373 374 } 375