2 * Unit test suite for resource functions.
4 * Copyright 2006 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
26 static const char filename
[] = "test_.exe";
29 static int build_exe( void )
31 IMAGE_DOS_HEADER
*dos
;
33 IMAGE_SECTION_HEADER
*sec
;
34 IMAGE_OPTIONAL_HEADER
*opt
;
38 const int page_size
= 0x1000;
40 memset( page
, 0, sizeof page
);
43 dos
->e_magic
= IMAGE_DOS_SIGNATURE
;
44 dos
->e_lfanew
= sizeof *dos
;
48 nt
->Signature
= IMAGE_NT_SIGNATURE
;
49 nt
->FileHeader
.Machine
= IMAGE_FILE_MACHINE_I386
;
50 nt
->FileHeader
.NumberOfSections
= 2;
51 nt
->FileHeader
.SizeOfOptionalHeader
= sizeof nt
->OptionalHeader
;
52 nt
->FileHeader
.Characteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
| IMAGE_FILE_DLL
;
54 opt
= &nt
->OptionalHeader
;
56 opt
->Magic
= IMAGE_NT_OPTIONAL_HDR_MAGIC
;
57 opt
->MajorLinkerVersion
= 1;
58 opt
->BaseOfCode
= 0x10;
59 opt
->ImageBase
= 0x10000000;
60 opt
->MajorOperatingSystemVersion
= 4;
61 opt
->MajorImageVersion
= 1;
62 opt
->MajorSubsystemVersion
= 4;
63 opt
->SizeOfHeaders
= sizeof *dos
+ sizeof *nt
+ sizeof *sec
* 2;
64 opt
->SizeOfImage
= page_size
*3;
65 opt
->Subsystem
= IMAGE_SUBSYSTEM_WINDOWS_CUI
;
67 /* if SectionAlignment and File alignment are not specified */
68 /* UpdateResource fails trying to create a huge temporary file */
69 opt
->SectionAlignment
= page_size
;
70 opt
->FileAlignment
= page_size
;
74 memcpy( sec
[0].Name
, ".rodata", 8 );
75 sec
[0].Misc
.VirtualSize
= page_size
;
76 sec
[0].PointerToRawData
= page_size
;
77 sec
[0].SizeOfRawData
= page_size
;
78 sec
[0].VirtualAddress
= page_size
;
79 sec
[0].Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
81 memcpy( sec
[1].Name
, ".rsrc", 6 );
82 sec
[1].Misc
.VirtualSize
= page_size
;
83 sec
[1].SizeOfRawData
= page_size
;
84 sec
[1].PointerToRawData
= page_size
*2;
85 sec
[1].VirtualAddress
= page_size
*2;
86 sec
[1].Characteristics
= IMAGE_SCN_CNT_INITIALIZED_DATA
| IMAGE_SCN_MEM_READ
;
88 file
= CreateFile(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
89 ok (file
!= INVALID_HANDLE_VALUE
, "failed to create file\n");
91 /* write out the header */
92 WriteFile( file
, page
, sizeof page
, &written
, NULL
);
94 /* write out an empty page for rodata */
95 memset( page
, 0, sizeof page
);
96 WriteFile( file
, page
, sizeof page
, &written
, NULL
);
98 /* write out an empty page for the resources */
99 memset( page
, 0, sizeof page
);
100 WriteFile( file
, page
, sizeof page
, &written
, NULL
);
107 static void update_missing_exe( void )
111 SetLastError(0xdeadbeef);
112 res
= BeginUpdateResource( filename
, TRUE
);
113 GLE
= GetLastError();
114 ok( res
== NULL
, "BeginUpdateResource should fail\n");
117 static void update_empty_exe( void )
119 HANDLE file
, res
, test
;
122 file
= CreateFile(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
123 ok (file
!= INVALID_HANDLE_VALUE
, "failed to create file\n");
127 res
= BeginUpdateResource( filename
, TRUE
);
128 if ( res
!= NULL
|| GetLastError() != ERROR_FILE_INVALID
)
130 ok( res
!= NULL
, "BeginUpdateResource failed\n");
132 /* check if it's possible to open the file now */
133 test
= CreateFile(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
134 ok (test
!= INVALID_HANDLE_VALUE
, "failed to create file\n");
138 r
= EndUpdateResource( res
, FALSE
);
139 ok( r
== FALSE
, "EndUpdateResource failed\n");
142 skip( "Can't update resource in empty file\n" );
144 res
= BeginUpdateResource( filename
, FALSE
);
145 ok( res
== NULL
, "BeginUpdateResource failed\n");
148 static void update_resources_none( void )
153 res
= BeginUpdateResource( filename
, FALSE
);
154 ok( res
!= NULL
, "BeginUpdateResource failed\n");
156 r
= EndUpdateResource( res
, FALSE
);
157 ok( r
, "EndUpdateResource failed\n");
160 static void update_resources_delete( void )
165 res
= BeginUpdateResource( filename
, TRUE
);
166 ok( res
!= NULL
, "BeginUpdateResource failed\n");
168 r
= EndUpdateResource( res
, FALSE
);
169 ok( r
, "EndUpdateResource failed\n");
172 static void update_resources_version(void)
176 char foo
[] = "red and white";
178 res
= BeginUpdateResource( filename
, TRUE
);
179 ok( res
!= NULL
, "BeginUpdateResource failed\n");
181 if (0) /* this causes subsequent tests to fail on Vista */
183 r
= UpdateResource( res
,
184 MAKEINTRESOURCE(0x1230),
185 MAKEINTRESOURCE(0x4567),
188 ok( r
== FALSE
, "UpdateResource failed\n");
191 r
= UpdateResource( res
,
192 MAKEINTRESOURCE(0x1230),
193 MAKEINTRESOURCE(0x4567),
196 ok( r
== TRUE
, "UpdateResource failed: %d\n", GetLastError());
198 r
= EndUpdateResource( res
, FALSE
);
199 ok( r
, "EndUpdateResource failed: %d\n", GetLastError());
203 typedef void (*res_check_func
)( IMAGE_RESOURCE_DIRECTORY
* );
205 static void check_empty( IMAGE_RESOURCE_DIRECTORY
*dir
)
209 ok( dir
->NumberOfNamedEntries
== 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir
->NumberOfNamedEntries
);
210 ok( dir
->NumberOfIdEntries
== 0, "NumberOfIdEntries should be 0 instead of %d\n", dir
->NumberOfIdEntries
);
212 pad
= (char*) &dir
[1];
214 ok( !memcmp( pad
, "PADDINGXXPADDING", 16), "padding wrong\n");
217 static void check_not_empty( IMAGE_RESOURCE_DIRECTORY
*dir
)
219 ok( dir
->NumberOfNamedEntries
== 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir
->NumberOfNamedEntries
);
220 ok( dir
->NumberOfIdEntries
== 1, "NumberOfIdEntries should be 1 instead of %d\n", dir
->NumberOfIdEntries
);
223 static void check_exe( res_check_func fn
)
225 IMAGE_DOS_HEADER
*dos
;
226 IMAGE_NT_HEADERS
*nt
;
227 IMAGE_SECTION_HEADER
*sec
;
228 IMAGE_RESOURCE_DIRECTORY
*dir
;
229 HANDLE file
, mapping
;
232 file
= CreateFile(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
233 ok (file
!= INVALID_HANDLE_VALUE
, "failed to create file (%d)\n", GetLastError());
235 length
= GetFileSize( file
, NULL
);
236 ok( length
== 0x3000, "file size wrong\n");
238 mapping
= CreateFileMapping( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
239 ok (mapping
!= NULL
, "failed to create file\n");
241 dos
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, length
);
242 ok( dos
!= NULL
, "failed to map file\n");
247 nt
= (void*) ((BYTE
*) dos
+ dos
->e_lfanew
);
248 ok( nt
->FileHeader
.NumberOfSections
== 2, "number of sections wrong\n" );
250 if (nt
->FileHeader
.NumberOfSections
< 2)
253 sec
= (void*) &nt
[1];
255 ok( !memcmp(sec
[1].Name
, ".rsrc", 6), "resource section name wrong\n");
257 dir
= (void*) ((BYTE
*) dos
+ sec
[1].VirtualAddress
);
259 ok( dir
->Characteristics
== 0, "Characteristics wrong\n");
260 ok( dir
->TimeDateStamp
== 0 || abs( dir
->TimeDateStamp
- GetTickCount() ) < 1000 /* nt4 */,
261 "TimeDateStamp wrong %u\n", dir
->TimeDateStamp
);
262 ok( dir
->MajorVersion
== 4, "MajorVersion wrong\n");
263 ok( dir
->MinorVersion
== 0, "MinorVersion wrong\n");
268 UnmapViewOfFile( dos
);
270 CloseHandle( mapping
);
275 static void test_find_resource(void)
279 rsrc
= FindResourceW( GetModuleHandle(0), (LPCWSTR
)MAKEINTRESOURCE(1), (LPCWSTR
)RT_MENU
);
280 ok( rsrc
!= 0, "resource not found\n" );
281 rsrc
= FindResourceExW( GetModuleHandle(0), (LPCWSTR
)RT_MENU
, (LPCWSTR
)MAKEINTRESOURCE(1),
282 MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
));
283 ok( rsrc
!= 0, "resource not found\n" );
284 rsrc
= FindResourceExW( GetModuleHandle(0), (LPCWSTR
)RT_MENU
, (LPCWSTR
)MAKEINTRESOURCE(1),
285 MAKELANGID( LANG_GERMAN
, SUBLANG_DEFAULT
));
286 ok( rsrc
!= 0, "resource not found\n" );
288 SetLastError( 0xdeadbeef );
289 rsrc
= FindResourceW( GetModuleHandle(0), (LPCWSTR
)MAKEINTRESOURCE(1), (LPCWSTR
)RT_DIALOG
);
290 ok( !rsrc
, "resource found\n" );
291 ok( GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND
, "wrong error %u\n", GetLastError() );
293 SetLastError( 0xdeadbeef );
294 rsrc
= FindResourceW( GetModuleHandle(0), (LPCWSTR
)MAKEINTRESOURCE(2), (LPCWSTR
)RT_MENU
);
295 ok( !rsrc
, "resource found\n" );
296 ok( GetLastError() == ERROR_RESOURCE_NAME_NOT_FOUND
, "wrong error %u\n", GetLastError() );
298 SetLastError( 0xdeadbeef );
299 rsrc
= FindResourceExW( GetModuleHandle(0), (LPCWSTR
)RT_MENU
, (LPCWSTR
)MAKEINTRESOURCE(1),
300 MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
301 ok( !rsrc
, "resource found\n" );
302 ok( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND
, "wrong error %u\n", GetLastError() );
304 SetLastError( 0xdeadbeef );
305 rsrc
= FindResourceExW( GetModuleHandle(0), (LPCWSTR
)RT_MENU
, (LPCWSTR
)MAKEINTRESOURCE(1),
306 MAKELANGID( LANG_FRENCH
, SUBLANG_DEFAULT
) );
307 ok( !rsrc
, "resource found\n" );
308 ok( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND
, "wrong error %u\n", GetLastError() );
313 DeleteFile( filename
);
314 update_missing_exe();
316 if (GLE
== ERROR_CALL_NOT_IMPLEMENTED
)
318 win_skip("Resource calls are not implemented\n");
324 update_resources_none();
325 check_exe( check_empty
);
326 update_resources_delete();
327 check_exe( check_empty
);
328 update_resources_version();
329 check_exe( check_not_empty
);
330 DeleteFile( filename
);
331 test_find_resource();