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] = 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 176 ResourceDirectory = &TestImage->NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; 177 ResourceDirectory->VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources); 178 ResourceDirectory->Size = sizeof(TEST_RESOURCES); 179 180 strcpy((char*)TestImage->SectionHeaders[0].Name, ".rsrc"); 181 TestImage->SectionHeaders[0].Misc.VirtualSize = sizeof(TEST_IMAGE); 182 TestImage->SectionHeaders[0].VirtualAddress = FIELD_OFFSET(TEST_IMAGE, Resources); 183 TestImage->SectionHeaders[0].SizeOfRawData = sizeof(TEST_IMAGE); 184 TestImage->SectionHeaders[0].PointerToRawData = FIELD_OFFSET(TEST_IMAGE, Resources); 185 TestImage->SectionHeaders[0].PointerToRelocations = 0; 186 TestImage->SectionHeaders[0].PointerToLinenumbers = 0; 187 TestImage->SectionHeaders[0].NumberOfRelocations = 0; 188 TestImage->SectionHeaders[0].NumberOfLinenumbers = 0; 189 TestImage->SectionHeaders[0].Characteristics = 0; 190 191 InitializeTestResource(TestImage, &TestImage->Resources); 192 } 193 194 #define ok_nwstr(str1, str2, count) \ 195 ok(wcsncmp((PWCHAR)str1, (PWCHAR)str2, count) == 0, \ 196 "string is wrong, expected: '%S', got '%S'\n", str1, str2); \ 197 198 #define ok_enumres(_Res, _Type, _Name, _Lang, _Data, _Size) \ 199 ok_dec((_Res)->Type, _Type); \ 200 if ((ULONG_PTR)(_Name) > 0xFFFF) \ 201 { \ 202 ok_dec(*(WORD*)((_Res)->Name), wcslen((PWCHAR)(_Name))); \ 203 ok_nwstr((PWCHAR)((_Res)->Name + 2), (PWCHAR)_Name, *(WORD*)((_Res)->Name)); \ 204 } \ 205 else \ 206 { \ 207 ok_dec((_Res)->Name, (ULONG_PTR)_Name); \ 208 } \ 209 ok_hex((_Res)->Language, _Lang); \ 210 ok_ptr((PVOID)(_Res)->Data, _Data); \ 211 ok_dec((_Res)->Size, _Size); \ 212 ok_dec((_Res)->Reserved, 0); 213 214 static 215 void 216 Test_Data(PTEST_IMAGE TestImage) 217 { 218 LDR_RESOURCE_INFO ResourceInfo; 219 LDR_ENUM_RESOURCE_INFO EnumRes[8]; 220 ULONG ResourceCount; 221 NTSTATUS Status; 222 223 InitializeTestImage(TestImage); 224 225 memset(EnumRes, 0xcc, sizeof(EnumRes)); 226 227 ResourceInfo.Type = 1; 228 ResourceInfo.Name = 1; 229 ResourceInfo.Language = 0x408; 230 ResourceCount = 8; 231 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, EnumRes); 232 ok_hex(Status, STATUS_SUCCESS); 233 ok_dec(ResourceCount, 8); 234 235 ok_ptr((PVOID)EnumRes[0].Data, TestImage->Resources.StringBuffer); 236 ok_dec(EnumRes[0].Size, 2); 237 238 ok_enumres(&EnumRes[0], 1, L"TEST", 0x409, TestImage->Resources.StringBuffer, 2) 239 ok_enumres(&EnumRes[1], 1, L"TEST", 0x407, TestImage->Resources.StringBuffer + 2, 4) 240 ok_enumres(&EnumRes[2], 1, 7, 0x408, TestImage->Resources.StringBuffer + 4, 6) 241 ok_enumres(&EnumRes[3], 1, 7, 0x406, TestImage->Resources.StringBuffer + 6, 8) 242 ok_enumres(&EnumRes[4], 2, L"LOL", 0x405, TestImage->Resources.StringBuffer + 8, 10) 243 ok_enumres(&EnumRes[5], 2, L"LOL", 0x403, TestImage->Resources.StringBuffer + 10, 12) 244 ok_enumres(&EnumRes[6], 2, L"xD", 0x402, TestImage->Resources.StringBuffer + 12, 14) 245 ok_enumres(&EnumRes[7], 2, L"xD", 0x404, TestImage->Resources.StringBuffer + 14, 16) 246 247 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, EnumRes); 248 ok_hex(Status, STATUS_SUCCESS); 249 ok_dec(ResourceCount, 4); 250 251 } 252 253 254 static 255 void 256 Test_Parameters(PTEST_IMAGE TestImage) 257 { 258 LDR_RESOURCE_INFO ResourceInfo; 259 LDR_ENUM_RESOURCE_INFO Resources[8]; 260 ULONG ResourceCount; 261 NTSTATUS Status; 262 263 InitializeTestImage(TestImage); 264 265 ResourceInfo.Type = 6; 266 ResourceInfo.Name = 1; 267 ResourceInfo.Language = 0x409; 268 269 ResourceCount = 8; 270 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources); 271 ok_hex(Status, STATUS_SUCCESS); 272 ok_dec(ResourceCount, 0); 273 274 ResourceInfo.Type = 1; 275 ResourceInfo.Name = 7; 276 ResourceInfo.Language = 0x406; 277 ResourceCount = 8; 278 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 279 ok_hex(Status, STATUS_SUCCESS); 280 ok_dec(ResourceCount, 8); 281 282 ResourceCount = 8; 283 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, Resources); 284 ok_hex(Status, STATUS_SUCCESS); 285 ok_dec(ResourceCount, 4); 286 287 ResourceCount = 8; 288 Status = LdrEnumResources(TestImage, &ResourceInfo, 2, &ResourceCount, Resources); 289 ok_hex(Status, STATUS_SUCCESS); 290 ok_dec(ResourceCount, 2); 291 292 ResourceCount = 8; 293 Status = LdrEnumResources(TestImage, &ResourceInfo, 3, &ResourceCount, Resources); 294 ok_hex(Status, STATUS_SUCCESS); 295 ok_dec(ResourceCount, 1); 296 297 ResourceCount = 8; 298 Status = LdrEnumResources(TestImage, &ResourceInfo, 99, &ResourceCount, Resources); 299 ok_hex(Status, STATUS_SUCCESS); 300 ok_dec(ResourceCount, 1); 301 302 ResourceCount = 0; 303 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 304 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 305 ok_dec(ResourceCount, 8); 306 307 ResourceCount = 7; 308 Status = LdrEnumResources(TestImage, &ResourceInfo, 0, &ResourceCount, Resources); 309 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 310 ok_dec(ResourceCount, 8); 311 312 ResourceCount = 8; 313 Status = LdrEnumResources(NULL, &ResourceInfo, 1, &ResourceCount, Resources); 314 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND); 315 ok_dec(ResourceCount, 0); 316 317 ResourceCount = 8; 318 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL); 319 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 320 ok_dec(ResourceCount, 4); 321 322 ResourceCount = 8; 323 _SEH2_TRY 324 { 325 Status = LdrEnumResources(NULL, NULL, 0, NULL, NULL); 326 } 327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 328 { 329 Status = 0xDeadC0de; 330 } 331 _SEH2_END 332 ok_hex(Status, 0xDeadC0de); 333 334 ResourceCount = 42; 335 _SEH2_TRY 336 { 337 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, NULL, Resources); 338 } 339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 340 { 341 Status = 0xDeadC0de; 342 } 343 _SEH2_END 344 ok_hex(Status, 0xDeadC0de); 345 ok_dec(ResourceCount, 42); 346 347 ResourceCount = 8; 348 Status = LdrEnumResources(TestImage + 2, &ResourceInfo, 1, &ResourceCount, NULL); 349 ok_hex(Status, STATUS_RESOURCE_DATA_NOT_FOUND); 350 ok_dec(ResourceCount, 0); 351 352 TestImage->Resources.TypeEntries[0].DataIsDirectory = 0; 353 Status = LdrEnumResources(TestImage, &ResourceInfo, 1, &ResourceCount, NULL); 354 ok_hex(Status, STATUS_INVALID_IMAGE_FORMAT); 355 ok_dec(ResourceCount, 0); 356 357 } 358 359 START_TEST(LdrEnumResources) 360 { 361 TEST_IMAGE TestImage; 362 363 Test_Parameters(&TestImage); 364 Test_Data(&TestImage); 365 366 } 367