Add missing '\n's in traces.
[wine] / dlls / kernel32 / tests / resource.c
1 /*
2  * Unit test suite for environment functions.
3  *
4  * Copyright 2006 Mike McCormack
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <windows.h>
22 #include <stdio.h>
23
24 #include "wine/test.h"
25
26 static const char filename[] = "test_.exe";
27
28 static int build_exe( void )
29 {
30     IMAGE_DOS_HEADER *dos;
31     IMAGE_NT_HEADERS *nt;
32     IMAGE_SECTION_HEADER *sec;
33     IMAGE_OPTIONAL_HEADER *opt;
34     HANDLE file;
35     DWORD written;
36     BYTE page[0x1000];
37     const int page_size = 0x1000;
38
39     memset( page, 0, sizeof page );
40
41     dos = (void*) page;
42     dos->e_magic = IMAGE_DOS_SIGNATURE;
43     dos->e_lfanew = sizeof *dos;
44
45     nt = (void*) &dos[1];
46
47     nt->Signature = IMAGE_NT_SIGNATURE;
48     nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
49     nt->FileHeader.NumberOfSections = 2;
50     nt->FileHeader.SizeOfOptionalHeader = sizeof nt->OptionalHeader;
51     nt->FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
52
53     opt = &nt->OptionalHeader;
54
55     opt->Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
56     opt->MajorLinkerVersion = 1;
57     opt->BaseOfCode = 0x10;
58     opt->ImageBase = 0x10000000;
59     opt->MajorOperatingSystemVersion = 4;
60     opt->MajorImageVersion = 1;
61     opt->MajorSubsystemVersion = 4;
62     opt->SizeOfHeaders = sizeof *dos + sizeof *nt + sizeof *sec * 2;
63     opt->SizeOfImage = page_size*3;
64     opt->Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
65
66     /* if SectionAlignment and File alignment are not specified */
67     /* UpdateResource fails trying to create a huge temporary file */
68     opt->SectionAlignment = page_size;
69     opt->FileAlignment = page_size;
70
71     sec = (void*) &nt[1];
72
73     memcpy( sec[0].Name, ".rodata", 8 );
74     sec[0].Misc.VirtualSize = page_size;
75     sec[0].PointerToRawData = page_size;
76     sec[0].SizeOfRawData = page_size;
77     sec[0].VirtualAddress = page_size;
78     sec[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
79
80     memcpy( sec[1].Name, ".rsrc", 6 );
81     sec[1].Misc.VirtualSize = page_size;
82     sec[1].SizeOfRawData = page_size;
83     sec[1].PointerToRawData = page_size*2;
84     sec[1].VirtualAddress = page_size*2;
85     sec[1].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
86
87     file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
88     ok (file != INVALID_HANDLE_VALUE, "failed to create file\n");
89
90     /* write out the header */
91     WriteFile( file, page, sizeof page, &written, NULL );
92
93     /* write out an empty page for rodata */
94     memset( page, 0, sizeof page );
95     WriteFile( file, page, sizeof page, &written, NULL );
96
97     /* write out an empty page for the resources */
98     memset( page, 0, sizeof page );
99     WriteFile( file, page, sizeof page, &written, NULL );
100
101     CloseHandle( file );
102
103     return 0;
104 }
105
106 static void update_missing_exe( void )
107 {
108     HANDLE res;
109
110     res = BeginUpdateResource( filename, TRUE );
111     ok( res == NULL, "BeginUpdateResource should fail\n");
112 }
113
114 static void update_empty_exe( void )
115 {
116     HANDLE file, res, test;
117     BOOL r;
118
119     file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
120     ok (file != INVALID_HANDLE_VALUE, "failed to create file\n");
121
122     CloseHandle( file );
123
124     res = BeginUpdateResource( filename, TRUE );
125     ok( res != NULL, "BeginUpdateResource failed\n");
126
127     /* check if it's possible to open the file now */
128     test = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
129     ok (test != INVALID_HANDLE_VALUE, "failed to create file\n");
130
131     CloseHandle( test );
132
133     r = EndUpdateResource( res, FALSE );
134     ok( r == FALSE, "EndUpdateResouce failed\n");
135
136     res = BeginUpdateResource( filename, FALSE );
137     ok( res == NULL, "BeginUpdateResource failed\n");
138 }
139
140 static void update_resources_none( void )
141 {
142     HMODULE res;
143     BOOL r;
144
145     res = BeginUpdateResource( filename, FALSE );
146     ok( res != NULL, "BeginUpdateResource failed\n");
147
148     r = EndUpdateResource( res, FALSE );
149     ok( r, "EndUpdateResouce failed\n");
150 }
151
152 static void update_resources_delete( void )
153 {
154     HMODULE res;
155     BOOL r;
156
157     res = BeginUpdateResource( filename, TRUE );
158     ok( res != NULL, "BeginUpdateResource failed\n");
159
160     r = EndUpdateResource( res, FALSE );
161     ok( r, "EndUpdateResouce failed\n");
162 }
163
164 void update_resources_version(void)
165 {
166     HANDLE res = NULL;
167     BOOL r;
168     char foo[] = "red and white";
169
170     res = BeginUpdateResource( filename, TRUE );
171     ok( res != NULL, "BeginUpdateResource failed\n");
172
173     r = UpdateResource( res,
174                         MAKEINTRESOURCE(0x1230),
175                         MAKEINTRESOURCE(0x4567),
176                         0xabcd,
177                         NULL, 0 );
178     ok( r == FALSE, "UpdateResouce failed\n");
179
180     r = UpdateResource( res,
181                         MAKEINTRESOURCE(0x1230),
182                         MAKEINTRESOURCE(0x4567),
183                         0xabcd,
184                         foo, sizeof foo );
185     ok( r == TRUE, "UpdateResouce failed\n");
186
187     r = EndUpdateResource( res, FALSE );
188     ok( r, "EndUpdateResouce failed\n");
189 }
190
191
192 typedef void (*res_check_func)( IMAGE_RESOURCE_DIRECTORY* );
193
194 void check_empty( IMAGE_RESOURCE_DIRECTORY *dir )
195 {
196     char *pad;
197
198     ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
199     ok( dir->NumberOfIdEntries == 0, "NumberOfIdEntries should be 0 instead of %d\n", dir->NumberOfIdEntries);
200
201     pad = (char*) &dir[1];
202
203     ok( !memcmp( pad, "PADDINGXXPADDING", 16), "padding wrong\n");
204 }
205
206 void check_not_empty( IMAGE_RESOURCE_DIRECTORY *dir )
207 {
208     ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
209     ok( dir->NumberOfIdEntries == 1, "NumberOfIdEntries should be 1 instead of %d\n", dir->NumberOfIdEntries);
210 }
211
212 void check_exe( res_check_func fn )
213 {
214     IMAGE_DOS_HEADER *dos;
215     IMAGE_NT_HEADERS *nt;
216     IMAGE_SECTION_HEADER *sec;
217     IMAGE_RESOURCE_DIRECTORY *dir;
218     HANDLE file, mapping;
219     DWORD length;
220
221     file = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
222     ok (file != INVALID_HANDLE_VALUE, "failed to create file (%d)\n", GetLastError());
223
224     length = GetFileSize( file, NULL );
225     ok( length == 0x3000, "file size wrong\n");
226
227     mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
228     ok (mapping != NULL, "failed to create file\n");
229
230     dos = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
231     ok( dos != NULL, "failed to map file\n");
232
233     if (!dos)
234         goto end;
235
236     nt = (void*) ((BYTE*) dos + dos->e_lfanew);
237     ok( nt->FileHeader.NumberOfSections == 2, "number of sections wrong\n" );
238
239     if (nt->FileHeader.NumberOfSections < 2)
240         goto end;
241
242     sec = (void*) &nt[1];
243
244     ok( !memcmp(sec[1].Name, ".rsrc", 6), "resource section name wrong\n");
245
246     dir = (void*) ((BYTE*) dos + sec[1].VirtualAddress);
247
248     ok( dir->Characteristics == 0, "Characteristics wrong\n");
249     ok( dir->TimeDateStamp == 0, "TimeDateStamp wrong\n");
250     ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
251     ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
252
253     fn( dir );
254
255 end:
256     UnmapViewOfFile( dos );
257
258     CloseHandle( mapping );
259
260     CloseHandle( file );
261 }
262
263 START_TEST(resource)
264 {
265     DeleteFile( filename );
266     update_missing_exe();
267     update_empty_exe();
268     build_exe();
269     update_resources_none();
270     check_exe( check_empty );
271     update_resources_delete();
272     check_exe( check_empty );
273     update_resources_version();
274     check_exe( check_not_empty );
275     DeleteFile( filename );
276 }