kernel32: Enhance EndUpdateResource.
This commit is contained in:
parent
0fbe445871
commit
a610fc17d8
|
@ -1372,10 +1372,7 @@ static IMAGE_SECTION_HEADER *get_resource_section( void *base, DWORD mapping_siz
|
|||
break;
|
||||
|
||||
if (i == num_sections)
|
||||
{
|
||||
FIXME(".rsrc doesn't exist\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &sec[i];
|
||||
}
|
||||
|
@ -1400,7 +1397,7 @@ static BOOL write_raw_resources( QUEUEDUPDATES *updates )
|
|||
{
|
||||
static const WCHAR prefix[] = { 'r','e','s','u',0 };
|
||||
WCHAR tempdir[MAX_PATH], tempfile[MAX_PATH];
|
||||
DWORD mapping_size, section_size, old_size;
|
||||
DWORD section_size;
|
||||
BOOL ret = FALSE;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
@ -1449,21 +1446,35 @@ static BOOL write_raw_resources( QUEUEDUPDATES *updates )
|
|||
goto done;
|
||||
}
|
||||
|
||||
sec = get_resource_section( write_map->base, write_map->size );
|
||||
if (!sec)
|
||||
if (nt->OptionalHeader.FileAlignment <= 0)
|
||||
{
|
||||
ERR("invalid file alignment %04x\n", nt->OptionalHeader.FileAlignment);
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec = get_resource_section( write_map->base, write_map->size );
|
||||
if (!sec) /* no section, add one */
|
||||
{
|
||||
DWORD num_sections;
|
||||
|
||||
sec = get_section_header( write_map->base, write_map->size, &num_sections );
|
||||
if (!sec)
|
||||
goto done;
|
||||
|
||||
sec += num_sections;
|
||||
nt->FileHeader.NumberOfSections++;
|
||||
|
||||
memset( sec, 0, sizeof *sec );
|
||||
memcpy( sec->Name, ".rsrc", 5 );
|
||||
sec->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
|
||||
sec->VirtualAddress = nt->OptionalHeader.SizeOfImage;
|
||||
}
|
||||
|
||||
if (!sec->PointerToRawData) /* empty section */
|
||||
{
|
||||
sec->PointerToRawData = write_map->size;
|
||||
sec->PointerToRawData = write_map->size + (-write_map->size) % nt->OptionalHeader.FileAlignment;
|
||||
sec->SizeOfRawData = 0;
|
||||
}
|
||||
else if ((sec->SizeOfRawData + sec->PointerToRawData) != write_map->size)
|
||||
{
|
||||
FIXME(".rsrc isn't at the end of the image %08x + %08x != %08x for %s\n",
|
||||
sec->SizeOfRawData, sec->PointerToRawData, write_map->size, debugstr_w(updates->pFileName));
|
||||
goto done;
|
||||
}
|
||||
|
||||
TRACE("before .rsrc at %08x, size %08x\n", sec->PointerToRawData, sec->SizeOfRawData);
|
||||
|
||||
|
@ -1471,38 +1482,85 @@ static BOOL write_raw_resources( QUEUEDUPDATES *updates )
|
|||
|
||||
/* round up the section size */
|
||||
section_size = res_size.total_size;
|
||||
section_size += (-section_size) % nt->OptionalHeader.SectionAlignment;
|
||||
|
||||
mapping_size = sec->PointerToRawData + section_size;
|
||||
section_size += (-section_size) % nt->OptionalHeader.FileAlignment;
|
||||
|
||||
TRACE("requires %08x (%08x) bytes\n", res_size.total_size, section_size );
|
||||
|
||||
/* check if the file size needs to be changed */
|
||||
if (section_size != sec->SizeOfRawData)
|
||||
{
|
||||
old_size = write_map->size;
|
||||
DWORD old_size = write_map->size;
|
||||
DWORD virtual_section_size = res_size.total_size + (-res_size.total_size) % nt->OptionalHeader.SectionAlignment;
|
||||
int delta = section_size - (sec->SizeOfRawData + (-sec->SizeOfRawData) % nt->OptionalHeader.FileAlignment);
|
||||
int rva_delta = virtual_section_size -
|
||||
(sec->Misc.VirtualSize + (-sec->Misc.VirtualSize) % nt->OptionalHeader.SectionAlignment);
|
||||
BOOL rsrc_is_last = sec->PointerToRawData + sec->SizeOfRawData == old_size;
|
||||
/* align .rsrc size when possible */
|
||||
DWORD mapping_size = rsrc_is_last ? sec->PointerToRawData + section_size : old_size + delta;
|
||||
|
||||
/* postpone file truncation if there are some data to be moved down from file end */
|
||||
BOOL resize_after = mapping_size < old_size && !rsrc_is_last;
|
||||
|
||||
TRACE("file size %08x -> %08x\n", old_size, mapping_size);
|
||||
|
||||
/* unmap the file before changing the file size */
|
||||
ret = resize_mapping( write_map, mapping_size );
|
||||
|
||||
/* get the pointers again - they might be different after remapping */
|
||||
nt = get_nt_header( write_map->base, mapping_size );
|
||||
if (!nt)
|
||||
if (!resize_after)
|
||||
{
|
||||
ERR("couldn't get NT header\n");
|
||||
goto done;
|
||||
/* unmap the file before changing the file size */
|
||||
ret = resize_mapping( write_map, mapping_size );
|
||||
|
||||
/* get the pointers again - they might be different after remapping */
|
||||
nt = get_nt_header( write_map->base, mapping_size );
|
||||
if (!nt)
|
||||
{
|
||||
ERR("couldn't get NT header\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec = get_resource_section( write_map->base, mapping_size );
|
||||
if (!sec)
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec = get_resource_section( write_map->base, mapping_size );
|
||||
if (!sec)
|
||||
goto done;
|
||||
if (!rsrc_is_last) /* not last section, relocate trailing sections */
|
||||
{
|
||||
IMAGE_SECTION_HEADER *s;
|
||||
DWORD tail_start = sec->PointerToRawData + sec->SizeOfRawData;
|
||||
DWORD i, num_sections = 0;
|
||||
|
||||
memmove( (char*)write_map->base + tail_start + delta, (char*)write_map->base + tail_start, old_size - tail_start );
|
||||
|
||||
s = get_section_header( write_map->base, mapping_size, &num_sections );
|
||||
|
||||
for (i=0; i<num_sections; i++)
|
||||
{
|
||||
if (s[i].PointerToRawData > sec->PointerToRawData)
|
||||
{
|
||||
s[i].PointerToRawData += delta;
|
||||
s[i].VirtualAddress += rva_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resize_after)
|
||||
{
|
||||
ret = resize_mapping( write_map, mapping_size );
|
||||
|
||||
nt = get_nt_header( write_map->base, mapping_size );
|
||||
if (!nt)
|
||||
{
|
||||
ERR("couldn't get NT header\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
sec = get_resource_section( write_map->base, mapping_size );
|
||||
if (!sec)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* adjust the PE header information */
|
||||
nt->OptionalHeader.SizeOfImage += (mapping_size - old_size);
|
||||
sec->SizeOfRawData = section_size;
|
||||
sec->Misc.VirtualSize = section_size;
|
||||
sec->Misc.VirtualSize = virtual_section_size;
|
||||
nt->OptionalHeader.SizeOfImage += rva_delta;
|
||||
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = res_size.total_size;
|
||||
nt->OptionalHeader.SizeOfInitializedData = get_init_data_size( write_map->base, mapping_size );
|
||||
}
|
||||
|
|
|
@ -26,16 +26,180 @@
|
|||
static const char filename[] = "test_.exe";
|
||||
static DWORD GLE;
|
||||
|
||||
static int build_exe( void )
|
||||
enum {
|
||||
page_size = 0x1000,
|
||||
rva_rsrc_start = page_size * 3,
|
||||
max_sections = 3
|
||||
} constants;
|
||||
|
||||
/* rodata @ [0x1000-0x3000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rodata_1 =
|
||||
{
|
||||
".rodata", {2*page_size}, page_size, 2*page_size, page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rodata @ [0x1000-0x4000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rodata_2 =
|
||||
{
|
||||
".rodata", {3*page_size}, page_size, 3*page_size, page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rodata @ [0x1000-0x2000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rodata_3 =
|
||||
{
|
||||
".rodata", {page_size}, page_size, page_size, page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x3000-0x4000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_1 =
|
||||
{
|
||||
".rsrc\0\0", {page_size}, rva_rsrc_start, page_size, rva_rsrc_start, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x4000-0x5000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_2 =
|
||||
{
|
||||
".rsrc\0\0", {page_size}, 4*page_size, page_size, 4*page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x2000-0x4000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_3 =
|
||||
{
|
||||
".rsrc\0\0", {2*page_size}, rva_rsrc_start-page_size, 2*page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x2000-0x3000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_4 =
|
||||
{
|
||||
".rsrc\0\0", {page_size}, rva_rsrc_start-page_size, page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x3000-0x6000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_5 =
|
||||
{
|
||||
".rsrc\0\0", {3*page_size}, rva_rsrc_start, 3*page_size, rva_rsrc_start, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x4000-0x7000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_6 =
|
||||
{
|
||||
".rsrc\0\0", {3*page_size}, 4*page_size, 3*page_size, 4*page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x2000-0x5000) */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_7 =
|
||||
{
|
||||
".rsrc\0\0", {3*page_size}, 2*page_size, 3*page_size, 2*page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* rsrc @ [0x3000-0x4000), small SizeOfRawData */
|
||||
static const IMAGE_SECTION_HEADER sh_rsrc_8 =
|
||||
{
|
||||
".rsrc\0\0", {page_size}, rva_rsrc_start, 8, rva_rsrc_start, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* reloc @ [0x4000-0x5000) */
|
||||
static const IMAGE_SECTION_HEADER sh_junk =
|
||||
{
|
||||
".reloc\0", {page_size}, 4*page_size, page_size, 4*page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
/* reloc @ [0x6000-0x7000) */
|
||||
static const IMAGE_SECTION_HEADER sh_junk_2 =
|
||||
{
|
||||
".reloc\0", {page_size}, 6*page_size, page_size, 6*page_size, 0, 0, 0, 0,
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
};
|
||||
|
||||
typedef struct _sec_build
|
||||
{
|
||||
const IMAGE_SECTION_HEADER *sect_in[max_sections];
|
||||
} sec_build;
|
||||
|
||||
typedef struct _sec_verify
|
||||
{
|
||||
const IMAGE_SECTION_HEADER *sect_out[max_sections];
|
||||
DWORD length;
|
||||
int rsrc_section;
|
||||
DWORD NumberOfNamedEntries, NumberOfIdEntries;
|
||||
} sec_verify;
|
||||
|
||||
static const struct _sec_variants
|
||||
{
|
||||
sec_build build;
|
||||
sec_verify chk_none, chk_delete, chk_version, chk_bigdata;
|
||||
} sec_variants[] =
|
||||
{
|
||||
/* .rsrc is the last section, data directory entry points to whole section */
|
||||
{
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
|
||||
{{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
|
||||
},
|
||||
/* single .rodata section with compatible characteristics, data directory entry points to section end */
|
||||
/* Vista+ - existing section isn't used, new section is created at the end of file */
|
||||
/* NT4/2000/2003 - image is broken */
|
||||
#if 0
|
||||
{
|
||||
{{&sh_rodata_2, NULL, NULL}},
|
||||
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 1},
|
||||
{{&sh_rodata_2, &sh_rsrc_6, NULL}, 7*page_size, 1, 0, 1}
|
||||
},
|
||||
#endif
|
||||
/* .rsrc is the last section, data directory entry points to section end */
|
||||
/* Vista+ - resources are moved to section start (trashing data that could be there), and section is trimmed */
|
||||
/* NT4/2000/2003 - resources are moved to section start (trashing data that could be there); section isn't trimmed */
|
||||
{
|
||||
{{&sh_rodata_3, &sh_rsrc_3, NULL}},
|
||||
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 1},
|
||||
{{&sh_rodata_3, &sh_rsrc_7, NULL}, 5*page_size, 1, 0, 1}
|
||||
},
|
||||
/* .rsrc is not the last section */
|
||||
/* section is reused; sections after .rsrc are shifted to give space to rsrc (in-image offset and RVA!) */
|
||||
{
|
||||
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 1},
|
||||
{{&sh_rodata_1, &sh_rsrc_5, &sh_junk_2}, 7*page_size, 1, 0, 1}
|
||||
},
|
||||
/* .rsrc is the last section, data directory entry points to whole section, file size is not aligned on FileAlign */
|
||||
{
|
||||
{{&sh_rodata_1, &sh_rsrc_8, NULL}},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
|
||||
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
|
||||
{{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
|
||||
}
|
||||
};
|
||||
|
||||
static int build_exe( const sec_build* sec_descr )
|
||||
{
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
IMAGE_OPTIONAL_HEADER *opt;
|
||||
HANDLE file;
|
||||
DWORD written;
|
||||
BYTE page[0x1000];
|
||||
const int page_size = 0x1000;
|
||||
DWORD written, i, file_size;
|
||||
BYTE page[page_size];
|
||||
|
||||
memset( page, 0, sizeof page );
|
||||
|
||||
|
@ -47,7 +211,7 @@ static int build_exe( void )
|
|||
|
||||
nt->Signature = IMAGE_NT_SIGNATURE;
|
||||
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
|
||||
nt->FileHeader.NumberOfSections = 2;
|
||||
nt->FileHeader.NumberOfSections = 0;
|
||||
nt->FileHeader.SizeOfOptionalHeader = sizeof nt->OptionalHeader;
|
||||
nt->FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
|
||||
|
||||
|
@ -61,7 +225,7 @@ static int build_exe( void )
|
|||
opt->MajorImageVersion = 1;
|
||||
opt->MajorSubsystemVersion = 4;
|
||||
opt->SizeOfHeaders = sizeof *dos + sizeof *nt + sizeof *sec * 2;
|
||||
opt->SizeOfImage = page_size*3;
|
||||
opt->SizeOfImage = page_size;
|
||||
opt->Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
|
||||
/* if SectionAlignment and File alignment are not specified */
|
||||
|
@ -69,21 +233,27 @@ static int build_exe( void )
|
|||
opt->SectionAlignment = page_size;
|
||||
opt->FileAlignment = page_size;
|
||||
|
||||
opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].VirtualAddress = rva_rsrc_start;
|
||||
opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].Size = page_size;
|
||||
|
||||
sec = (void*) &nt[1];
|
||||
|
||||
memcpy( sec[0].Name, ".rodata", 8 );
|
||||
sec[0].Misc.VirtualSize = page_size;
|
||||
sec[0].PointerToRawData = page_size;
|
||||
sec[0].SizeOfRawData = page_size;
|
||||
sec[0].VirtualAddress = page_size;
|
||||
sec[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
|
||||
|
||||
memcpy( sec[1].Name, ".rsrc", 6 );
|
||||
sec[1].Misc.VirtualSize = page_size;
|
||||
sec[1].SizeOfRawData = page_size;
|
||||
sec[1].PointerToRawData = page_size*2;
|
||||
sec[1].VirtualAddress = page_size*2;
|
||||
sec[1].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
|
||||
file_size = 0;
|
||||
for ( i = 0; i < max_sections; i++ )
|
||||
if ( sec_descr->sect_in[i] )
|
||||
{
|
||||
DWORD virt_end_of_section = sec_descr->sect_in[i]->Misc.VirtualSize +
|
||||
sec_descr->sect_in[i]->VirtualAddress;
|
||||
DWORD phys_end_of_section = sec_descr->sect_in[i]->SizeOfRawData +
|
||||
sec_descr->sect_in[i]->PointerToRawData;
|
||||
memcpy( sec + nt->FileHeader.NumberOfSections, sec_descr->sect_in[i],
|
||||
sizeof(sec[0]) );
|
||||
nt->FileHeader.NumberOfSections++;
|
||||
if ( opt->SizeOfImage < virt_end_of_section )
|
||||
opt->SizeOfImage = virt_end_of_section;
|
||||
if ( file_size < phys_end_of_section )
|
||||
file_size = phys_end_of_section;
|
||||
}
|
||||
|
||||
file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
ok (file != INVALID_HANDLE_VALUE, "failed to create file\n");
|
||||
|
@ -91,13 +261,13 @@ static int build_exe( void )
|
|||
/* write out the header */
|
||||
WriteFile( file, page, sizeof page, &written, NULL );
|
||||
|
||||
/* write out an empty page for rodata */
|
||||
/* write out zeroed pages for sections */
|
||||
memset( page, 0, sizeof page );
|
||||
WriteFile( file, page, sizeof page, &written, NULL );
|
||||
|
||||
/* write out an empty page for the resources */
|
||||
memset( page, 0, sizeof page );
|
||||
WriteFile( file, page, sizeof page, &written, NULL );
|
||||
for ( i = page_size; i < file_size; i += page_size )
|
||||
{
|
||||
DWORD size = min(page_size, file_size - i);
|
||||
WriteFile( file, page, size, &written, NULL );
|
||||
}
|
||||
|
||||
CloseHandle( file );
|
||||
|
||||
|
@ -169,7 +339,7 @@ static void update_resources_delete( void )
|
|||
ok( r, "EndUpdateResource failed\n");
|
||||
}
|
||||
|
||||
static void update_resources_version(void)
|
||||
static void update_resources_version( void )
|
||||
{
|
||||
HANDLE res = NULL;
|
||||
BOOL r;
|
||||
|
@ -199,41 +369,41 @@ static void update_resources_version(void)
|
|||
ok( r, "EndUpdateResource failed: %d\n", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
typedef void (*res_check_func)( IMAGE_RESOURCE_DIRECTORY* );
|
||||
|
||||
static void check_empty( IMAGE_RESOURCE_DIRECTORY *dir )
|
||||
static void update_resources_bigdata( void )
|
||||
{
|
||||
char *pad;
|
||||
HANDLE res = NULL;
|
||||
BOOL r;
|
||||
char foo[2*page_size] = "foobar";
|
||||
|
||||
ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
|
||||
ok( dir->NumberOfIdEntries == 0, "NumberOfIdEntries should be 0 instead of %d\n", dir->NumberOfIdEntries);
|
||||
res = BeginUpdateResource( filename, TRUE );
|
||||
ok( res != NULL, "BeginUpdateResource succeeded\n");
|
||||
|
||||
pad = (char*) &dir[1];
|
||||
r = UpdateResource( res,
|
||||
MAKEINTRESOURCE(0x3012),
|
||||
MAKEINTRESOURCE(0x5647),
|
||||
0xcdba,
|
||||
foo, sizeof foo );
|
||||
ok( r == TRUE, "UpdateResource failed: %d\n", GetLastError());
|
||||
|
||||
ok( !memcmp( pad, "PADDINGXXPADDING", 16), "padding wrong\n");
|
||||
r = EndUpdateResource( res, FALSE );
|
||||
ok( r, "EndUpdateResource failed\n");
|
||||
}
|
||||
|
||||
static void check_not_empty( IMAGE_RESOURCE_DIRECTORY *dir )
|
||||
{
|
||||
ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
|
||||
ok( dir->NumberOfIdEntries == 1, "NumberOfIdEntries should be 1 instead of %d\n", dir->NumberOfIdEntries);
|
||||
}
|
||||
|
||||
static void check_exe( res_check_func fn )
|
||||
static void check_exe( const sec_verify *verify )
|
||||
{
|
||||
int i;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
IMAGE_RESOURCE_DIRECTORY *dir;
|
||||
HANDLE file, mapping;
|
||||
DWORD length;
|
||||
DWORD length, sec_count = 0;
|
||||
|
||||
file = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
|
||||
ok (file != INVALID_HANDLE_VALUE, "failed to create file (%d)\n", GetLastError());
|
||||
|
||||
length = GetFileSize( file, NULL );
|
||||
ok( length == 0x3000, "file size wrong\n");
|
||||
ok( length >= verify->length, "file size wrong\n");
|
||||
|
||||
mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
|
||||
ok (mapping != NULL, "failed to create file\n");
|
||||
|
@ -245,24 +415,36 @@ static void check_exe( res_check_func fn )
|
|||
goto end;
|
||||
|
||||
nt = (void*) ((BYTE*) dos + dos->e_lfanew);
|
||||
ok( nt->FileHeader.NumberOfSections == 2, "number of sections wrong\n" );
|
||||
|
||||
if (nt->FileHeader.NumberOfSections < 2)
|
||||
goto end;
|
||||
|
||||
sec = (void*) &nt[1];
|
||||
|
||||
ok( !memcmp(sec[1].Name, ".rsrc", 6), "resource section name wrong\n");
|
||||
for(i = 0; i < max_sections; i++)
|
||||
if (verify->sect_out[i])
|
||||
{
|
||||
ok( !memcmp(&verify->sect_out[i]->Name, &sec[sec_count].Name, 8), "section %d name wrong\n", sec_count);
|
||||
ok( verify->sect_out[i]->VirtualAddress == sec[sec_count].VirtualAddress, "section %d vaddr wrong\n", sec_count);
|
||||
ok( verify->sect_out[i]->SizeOfRawData <= sec[sec_count].SizeOfRawData, "section %d SizeOfRawData wrong (%d vs %d)\n", sec_count, verify->sect_out[i]->SizeOfRawData ,sec[sec_count].SizeOfRawData);
|
||||
ok( verify->sect_out[i]->PointerToRawData == sec[sec_count].PointerToRawData, "section %d PointerToRawData wrong\n", sec_count);
|
||||
ok( verify->sect_out[i]->Characteristics == sec[sec_count].Characteristics , "section %d characteristics wrong\n", sec_count);
|
||||
sec_count++;
|
||||
}
|
||||
|
||||
dir = (void*) ((BYTE*) dos + sec[1].VirtualAddress);
|
||||
ok( nt->FileHeader.NumberOfSections == sec_count, "number of sections wrong\n" );
|
||||
|
||||
ok( dir->Characteristics == 0, "Characteristics wrong\n");
|
||||
ok( dir->TimeDateStamp == 0 || abs( dir->TimeDateStamp - GetTickCount() ) < 1000 /* nt4 */,
|
||||
"TimeDateStamp wrong %u\n", dir->TimeDateStamp);
|
||||
ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
|
||||
ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
|
||||
if (verify->rsrc_section >= 0 && verify->rsrc_section < nt->FileHeader.NumberOfSections)
|
||||
{
|
||||
dir = (void*) ((BYTE*) dos + sec[verify->rsrc_section].VirtualAddress);
|
||||
|
||||
fn( dir );
|
||||
ok( dir->Characteristics == 0, "Characteristics wrong\n");
|
||||
ok( dir->TimeDateStamp == 0 || abs( dir->TimeDateStamp - GetTickCount() ) < 1000 /* nt4 */,
|
||||
"TimeDateStamp wrong %u\n", dir->TimeDateStamp);
|
||||
ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
|
||||
ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
|
||||
|
||||
ok( dir->NumberOfNamedEntries == verify->NumberOfNamedEntries, "NumberOfNamedEntries should be %d instead of %d\n",
|
||||
verify->NumberOfNamedEntries, dir->NumberOfNamedEntries);
|
||||
ok( dir->NumberOfIdEntries == verify->NumberOfIdEntries, "NumberOfIdEntries should be %d instead of %d\n",
|
||||
verify->NumberOfIdEntries, dir->NumberOfIdEntries);
|
||||
}
|
||||
|
||||
end:
|
||||
UnmapViewOfFile( dos );
|
||||
|
@ -310,6 +492,8 @@ static void test_find_resource(void)
|
|||
|
||||
START_TEST(resource)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
DeleteFile( filename );
|
||||
update_missing_exe();
|
||||
|
||||
|
@ -320,13 +504,20 @@ START_TEST(resource)
|
|||
}
|
||||
|
||||
update_empty_exe();
|
||||
build_exe();
|
||||
update_resources_none();
|
||||
check_exe( check_empty );
|
||||
update_resources_delete();
|
||||
check_exe( check_empty );
|
||||
update_resources_version();
|
||||
check_exe( check_not_empty );
|
||||
DeleteFile( filename );
|
||||
|
||||
for(i=0; i < sizeof( sec_variants ) / sizeof( sec_variants[0] ); i++)
|
||||
{
|
||||
const struct _sec_variants *sec = &sec_variants[i];
|
||||
build_exe( &sec->build );
|
||||
update_resources_none();
|
||||
check_exe( &sec->chk_none );
|
||||
update_resources_delete();
|
||||
check_exe( &sec->chk_delete );
|
||||
update_resources_version();
|
||||
check_exe( &sec->chk_version );
|
||||
update_resources_bigdata();
|
||||
check_exe( &sec->chk_bigdata );
|
||||
DeleteFile( filename );
|
||||
}
|
||||
test_find_resource();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue