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