[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / rostests / winetests / kernel32 / format_msg.c
1 /* Unit test suite for FormatMessageA/W
2 *
3 * Copyright 2002 Mike McCormack for CodeWeavers
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include <stdarg.h>
21
22 #include "wine/test.h"
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnls.h"
26
27 static DWORD __cdecl doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
28 LPSTR out, DWORD outsize, ... )
29 {
30 __ms_va_list list;
31 DWORD r;
32
33 __ms_va_start(list, outsize);
34 r = FormatMessageA(flags, src, msg_id,
35 lang_id, out, outsize, &list);
36 __ms_va_end(list);
37 return r;
38 }
39
40 static DWORD __cdecl doitW(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
41 LPWSTR out, DWORD outsize, ... )
42 {
43 __ms_va_list list;
44 DWORD r;
45
46 __ms_va_start(list, outsize);
47 r = FormatMessageW(flags, src, msg_id,
48 lang_id, out, outsize, &list);
49 __ms_va_end(list);
50 return r;
51 }
52
53 static void test_message_from_string_wide(void)
54 {
55 static const WCHAR test[] = {'t','e','s','t',0};
56 static const WCHAR empty[] = {0};
57 static const WCHAR te[] = {'t','e',0};
58 static const WCHAR st[] = {'s','t',0};
59 static const WCHAR t[] = {'t',0};
60 static const WCHAR e[] = {'e',0};
61 static const WCHAR s[] = {'s',0};
62 static const WCHAR fmt_null[] = {'%',0};
63 static const WCHAR fmt_tnull[] = {'t','e','s','t','%',0};
64 static const WCHAR fmt_1[] = {'%','1',0};
65 static const WCHAR fmt_12[] = {'%','1','%','2',0};
66 static const WCHAR fmt_123[] = {'%','1','%','3','%','2','%','1',0};
67 static const WCHAR fmt_123c[] = {'%','1','!','c','!','%','2','!','c','!','%','3','!','c','!','%','1','!','c','!',0};
68 static const WCHAR fmt_123lc[] = {'%','1','!','l','c','!','%','2','!','l','c','!','%','3','!','l','c','!','%','1','!','l','c','!',0};
69 static const WCHAR fmt_123wc[] = {'%','1','!','w','c','!','%','2','!','w','c','!','%','3','!','w','c','!','%','1','!','w','c','!',0};
70 static const WCHAR fmt_123C[] = {'%','1','!','C','!','%','2','!','C','!','%','3','!','C','!','%','1','!','C','!',0};
71 static const WCHAR fmt_123d[] = {'%','1','!','d','!','%','2','!','d','!','%','3','!','d','!',0};
72 static const WCHAR fmt_1s[] = {'%','1','!','s','!',0};
73 static const WCHAR fmt_s[] = {'%','!','s','!',0};
74 static const WCHAR fmt_ls[] = {'%','!','l','s','!',0};
75 static const WCHAR fmt_ws[] = {'%','!','w','s','!',0};
76 static const WCHAR fmt_S[] = {'%','!','S','!',0};
77 static const WCHAR fmt_14d[] = {'%','1','!','4','d','!',0};
78 static const WCHAR fmt_14x[] = {'%','1','!','4','x','!',0};
79 static const WCHAR fmt_14X[] = {'%','1','!','4','X','!',0};
80 static const WCHAR fmt_1_4X[] = {'%','1','!','-','4','X','!',0};
81 static const WCHAR fmt_1_4d[] = {'%','1','!','-','4','d','!',0};
82 static const WCHAR fmt_2pct[] = {' ','%','%','%','%',' ',0};
83 static const WCHAR fmt_2dot1d[] = {' ', '%','.','%','.',' ',' ','%','1','!','d','!',0};
84 static const WCHAR fmt_t0t[] = {'t','e','s','t','%','0','t','e','s','t',0};
85 static const WCHAR fmt_yah[] = {'y','a','h','%','!','%','0',' ',' ',' ',0};
86 static const WCHAR fmt_space[] = {'%',' ','%',' ',' ',' ',0};
87 static const WCHAR fmt_nrt[] = {'%','n','%','r','%','t',0};
88 static const WCHAR fmt_hi_lf[] = {'h','i','\n',0};
89 static const WCHAR fmt_hi_crlf[] = {'h','i','\r','\n',0};
90 static const WCHAR fmt_cr[] = {'\r',0};
91 static const WCHAR fmt_crcrlf[] = {'\r','\r','\n',0};
92 static const WCHAR fmt_13s[] = {'%','1','!','3','s','!',0};
93 static const WCHAR fmt_1os[] = {'%','1','!','*','s','!',0};
94 static const WCHAR fmt_142u[] = {'%','1','!','4','.','2','u','!',0};
95 static const WCHAR fmt_1oou[] = {'%','1','!','*','.','*','u','!',0};
96 static const WCHAR fmt_1oou1oou[] = {'%','1','!','*','.','*','u','!',',','%','1','!','*','.','*','u','!',0};
97 static const WCHAR fmt_1oou3oou[] = {'%','1','!','*','.','*','u','!',',','%','3','!','*','.','*','u','!',0};
98 static const WCHAR fmt_1oou4oou[] = {'%','1','!','*','.','*','u','!',',','%','4','!','*','.','*','u','!',0};
99
100 static const WCHAR s_123d[] = {'1','2','3',0};
101 static const WCHAR s_14d[] = {' ',' ',' ','1',0};
102 static const WCHAR s_14x[] = {' ',' ',' ','b',0};
103 static const WCHAR s_14X[] = {' ',' ',' ','B',0};
104 static const WCHAR s_1_4X[] = {'B',' ',' ',' ',0};
105 static const WCHAR s_14d2[] = {' ',' ','1','1',0};
106 static const WCHAR s_1_4d[] = {'1',' ',' ',' ',0};
107 static const WCHAR s_1AB[] = {' ','1','A','B',0};
108 static const WCHAR s_2pct[] = {' ','%','%',' ',0};
109 static const WCHAR s_2dot147[] = {' ','.','.',' ',' ','4','2','7',0};
110 static const WCHAR s_yah[] = {'y','a','h','!',0};
111 static const WCHAR s_space[] = {' ',' ',' ',' ',0};
112 static const WCHAR s_nrt[] = {'\r','\n','\r','\t',0};
113 static const WCHAR s_hi_crlf[] = {'h','i','\r','\n',0};
114 static const WCHAR s_crlf[] = {'\r','\n',0};
115 static const WCHAR s_crlfcrlf[] = {'\r','\n','\r','\n',0};
116 static const WCHAR s_hi_sp[] = {'h','i',' ',0};
117 static const WCHAR s_sp[] = {' ',0};
118 static const WCHAR s_2sp[] = {' ',' ',0};
119 static const WCHAR s_spt[] = {' ',' ','t',0};
120 static const WCHAR s_sp3t[] = {' ',' ',' ','t',0};
121 static const WCHAR s_sp03[] = {' ',' ','0','3',0};
122 static const WCHAR s_sp001[] = {' ',' ','0','0','1',0};
123 static const WCHAR s_sp001002[] = {' ',' ','0','0','1',',',' ','0','0','0','2',0};
124 static const WCHAR s_sp001sp002[] = {' ',' ','0','0','1',',',' ',' ','0','0','0','2',0};
125 static const WCHAR s_sp002sp001[] = {' ',' ','0','0','0','2',',',' ',' ','0','0','1',0};
126 static const WCHAR s_sp002sp003[] = {' ',' ','0','0','0','2',',',' ','0','0','0','0','3',0};
127 static const WCHAR s_sp001004[] = {' ',' ','0','0','1',',','0','0','0','0','0','4',0};
128
129 static const WCHAR init_buf[] = {'x', 'x', 'x', 'x', 'x', 'x'};
130 static const WCHAR broken_buf[] = {'t','e','s','t','x','x'};
131
132 WCHAR out[0x100] = {0};
133 DWORD r, error;
134
135 /* the basics */
136 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0,
137 0, out, sizeof(out)/sizeof(WCHAR), NULL);
138 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
139 ok(r==4, "failed: r=%d\n", r);
140
141 /* null string, crashes on Windows */
142 if (0)
143 {
144 SetLastError(0xdeadbeef);
145 memcpy(out, init_buf, sizeof(init_buf));
146 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
147 0, out, sizeof(out)/sizeof(WCHAR), NULL);
148 }
149
150 /* empty string */
151 SetLastError(0xdeadbeef);
152 memcpy(out, init_buf, sizeof(init_buf));
153 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, empty, 0,
154 0, out, sizeof(out)/sizeof(WCHAR), NULL);
155 error = GetLastError();
156 ok(!lstrcmpW(empty, out), "failed out=%s\n", wine_dbgstr_w(out));
157 ok(r==0, "succeeded: r=%d\n", r);
158 ok(error==0xdeadbeef, "last error %u\n", error);
159
160 /* format placeholder with no specifier */
161 SetLastError(0xdeadbeef);
162 memcpy(out, init_buf, sizeof(init_buf));
163 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_null, 0,
164 0, out, sizeof(out)/sizeof(WCHAR), NULL);
165 error = GetLastError();
166 ok(!memcmp(out, init_buf, sizeof(init_buf)),
167 "Expected the buffer to be unchanged\n");
168 ok(r==0, "succeeded: r=%d\n", r);
169 ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
170
171 /* test string with format placeholder with no specifier */
172 SetLastError(0xdeadbeef);
173 memcpy(out, init_buf, sizeof(init_buf));
174 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_tnull, 0,
175 0, out, sizeof(out)/sizeof(WCHAR), NULL);
176 error = GetLastError();
177 ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
178 broken(!memcmp(out, broken_buf, sizeof(broken_buf))), /* W2K3+ */
179 "Expected the buffer to be unchanged\n");
180 ok(r==0, "succeeded: r=%d\n", r);
181 ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
182
183 /* insertion with no variadic arguments */
184 SetLastError(0xdeadbeef);
185 memcpy(out, init_buf, sizeof(init_buf));
186 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
187 0, out, sizeof(out)/sizeof(WCHAR), NULL);
188 error = GetLastError();
189 ok(!memcmp(out, init_buf, sizeof(init_buf)),
190 "Expected the buffer to be unchanged\n");
191 ok(r==0, "succeeded: r=%d\n", r);
192 ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
193
194 SetLastError(0xdeadbeef);
195 memcpy(out, init_buf, sizeof(init_buf));
196 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1, 0,
197 0, out, sizeof(out)/sizeof(WCHAR), NULL);
198 error = GetLastError();
199 ok(!memcmp(out, init_buf, sizeof(init_buf)),
200 "Expected the buffer to be unchanged\n");
201 ok(r==0, "succeeded: r=%d\n", r);
202 ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
203
204 /* using the format feature */
205 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1s, 0,
206 0, out, sizeof(out)/sizeof(WCHAR), test);
207 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
208 ok(r==4,"failed: r=%d\n", r);
209
210 /* no format */
211 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
212 0, out, sizeof(out)/sizeof(WCHAR), test);
213 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
214 ok(r==4,"failed: r=%d\n", r);
215
216 /* two pieces */
217 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_12, 0,
218 0, out, sizeof(out)/sizeof(WCHAR), te, st);
219 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
220 ok(r==4,"failed: r=%d\n", r);
221
222 /* three pieces */
223 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123, 0,
224 0, out, sizeof(out)/sizeof(WCHAR), t, s, e);
225 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
226 ok(r==4,"failed: r=%d\n", r);
227
228 /* s doesn't seem to work in format strings */
229 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_s, 0,
230 0, out, sizeof(out)/sizeof(WCHAR), test);
231 ok(!lstrcmpW(&fmt_s[1], out), "failed out=%s\n", wine_dbgstr_w(out));
232 ok(r==3, "failed: r=%d\n", r);
233
234 /* nor ls */
235 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ls, 0,
236 0, out, sizeof(out)/sizeof(WCHAR), test);
237 ok(!lstrcmpW(&fmt_ls[1], out), "failed out=%s\n", wine_dbgstr_w(out));
238 ok(r==4, "failed: r=%d\n", r);
239
240 /* nor S */
241 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_S, 0,
242 0, out, sizeof(out)/sizeof(WCHAR), test);
243 ok(!lstrcmpW(&fmt_S[1], out), "failed out=%s\n", wine_dbgstr_w(out));
244 ok(r==3, "failed: r=%d\n", r);
245
246 /* nor ws */
247 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ws, 0,
248 0, out, sizeof(out)/sizeof(WCHAR), test);
249 ok(!lstrcmpW(&fmt_ws[1], out), "failed out=%s\n", wine_dbgstr_w(out));
250 ok(r==4, "failed: r=%d\n", r);
251
252 /* as characters */
253 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123c, 0,
254 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
255 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
256 ok(r==4,"failed: r=%d\n", r);
257
258 /* lc is unicode */
259 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123lc, 0,
260 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
261 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
262 ok(r==4,"failed: r=%d\n", r);
263
264 /* wc is unicode */
265 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123wc, 0,
266 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
267 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
268 ok(r==4,"failed: r=%d\n", r);
269
270 /* C is unicode */
271 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123C, 0,
272 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
273 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
274 ok(r==4,"failed: r=%d\n", r);
275
276 /* some numbers */
277 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123d, 0,
278 0, out, sizeof(out)/sizeof(WCHAR), 1, 2, 3);
279 ok(!lstrcmpW(s_123d, out), "failed out=%s\n", wine_dbgstr_w(out));
280 ok(r==3,"failed: r=%d\n", r);
281
282 /* a single digit with some spacing */
283 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0,
284 0, out, sizeof(out)/sizeof(WCHAR), 1);
285 ok(!lstrcmpW(s_14d, out), "failed out=%s\n", wine_dbgstr_w(out));
286
287 /* a single digit, left justified */
288 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4d, 0,
289 0, out, sizeof(out)/sizeof(CHAR), 1);
290 ok(!lstrcmpW(s_1_4d, out), "failed out=%s\n", wine_dbgstr_w(out));
291 ok(r==4,"failed: r=%d\n", r);
292
293 /* two digit decimal number */
294 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0,
295 0, out, sizeof(out)/sizeof(WCHAR), 11);
296 ok(!lstrcmpW(s_14d2, out), "failed out=%s\n", wine_dbgstr_w(out));
297 ok(r==4,"failed: r=%d\n", r);
298
299 /* a hex number */
300 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14x, 0,
301 0, out, sizeof(out)/sizeof(WCHAR), 11);
302 ok(!lstrcmpW(s_14x, out), "failed out=%s\n", wine_dbgstr_w(out));
303 ok(r==4,"failed: r=%d\n", r);
304
305 /* a hex number, upper case */
306 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0,
307 0, out, sizeof(out)/sizeof(WCHAR), 11);
308 ok(!lstrcmpW(s_14X, out), "failed out=%s\n", wine_dbgstr_w(out));
309 ok(r==4,"failed: r=%d\n", r);
310
311 /* a hex number, upper case, left justified */
312 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4X, 0,
313 0, out, sizeof(out)/sizeof(WCHAR), 11);
314 ok(!lstrcmpW(s_1_4X, out), "failed out=%s\n", wine_dbgstr_w(out));
315 ok(r==4,"failed: r=%d\n", r);
316
317 /* a long hex number, upper case */
318 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0,
319 0, out, sizeof(out)/sizeof(WCHAR), 0x1ab);
320 ok(!lstrcmpW(s_1AB, out), "failed out=%s\n", wine_dbgstr_w(out));
321 ok(r==4,"failed: r=%d\n", r);
322
323 /* two percent... */
324 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2pct, 0,
325 0, out, sizeof(out)/sizeof(WCHAR));
326 ok(!lstrcmpW(s_2pct, out), "failed out=%s\n", wine_dbgstr_w(out));
327 ok(r==4,"failed: r=%d\n", r);
328
329 /* periods are special cases */
330 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2dot1d, 0,
331 0, out, sizeof(out)/sizeof(WCHAR), 0x1ab);
332 ok(!lstrcmpW(s_2dot147, out), "failed out=%s\n", wine_dbgstr_w(out));
333 ok(r==8,"failed: r=%d\n", r);
334
335 /* %0 ends the line */
336 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_t0t, 0,
337 0, out, sizeof(out)/sizeof(WCHAR));
338 ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
339 ok(r==4,"failed: r=%d\n", r);
340
341 /* %! prints an exclamation */
342 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_yah, 0,
343 0, out, sizeof(out)/sizeof(WCHAR));
344 ok(!lstrcmpW(s_yah, out), "failed out=%s\n", wine_dbgstr_w(out));
345 ok(r==4,"failed: r=%d\n", r);
346
347 /* %space */
348 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_space, 0,
349 0, out, sizeof(out)/sizeof(WCHAR));
350 ok(!lstrcmpW(s_space, out), "failed out=%s\n", wine_dbgstr_w(out));
351 ok(r==4,"failed: r=%d\n", r);
352
353 /* %n yields \r\n, %r yields \r, %t yields \t */
354 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_nrt, 0,
355 0, out, sizeof(out)/sizeof(WCHAR));
356 ok(!lstrcmpW(s_nrt, out), "failed out=%s\n", wine_dbgstr_w(out));
357 ok(r==4,"failed: r=%d\n", r);
358
359 /* line feed */
360 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_lf, 0,
361 0, out, sizeof(out)/sizeof(WCHAR));
362 ok(!lstrcmpW(s_hi_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
363 ok(r==4,"failed: r=%d\n", r);
364
365 /* carriage return line feed */
366 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_crlf, 0,
367 0, out, sizeof(out)/sizeof(WCHAR));
368 ok(!lstrcmpW(s_hi_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
369 ok(r==4,"failed: r=%d\n", r);
370
371 /* carriage return */
372 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_cr, 0,
373 0, out, sizeof(out)/sizeof(WCHAR));
374 ok(!lstrcmpW(s_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
375 ok(r==2,"failed: r=%d\n", r);
376
377 /* double carriage return line feed */
378 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_crcrlf, 0,
379 0, out, sizeof(out)/sizeof(WCHAR));
380 ok(!lstrcmpW(s_crlfcrlf, out), "failed out=%s\n", wine_dbgstr_w(out));
381 ok(r==4,"failed: r=%d\n", r);
382
383 /* precision and width */
384
385 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_13s,
386 0, 0, out, sizeof(out)/sizeof(WCHAR), t );
387 ok(!lstrcmpW(s_spt, out),"failed out=[%s]\n", wine_dbgstr_w(out));
388 ok(r==3, "failed: r=%d\n",r);
389 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1os,
390 0, 0, out, sizeof(out)/sizeof(WCHAR), 4, t );
391 ok(!lstrcmpW( s_sp3t, out),"failed out=[%s]\n", wine_dbgstr_w(out));
392 ok(r==4,"failed: r=%d\n",r);
393 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_142u,
394 0, 0, out, sizeof(out)/sizeof(WCHAR), 3 );
395 ok(!lstrcmpW( s_sp03, out),"failed out=[%s]\n", wine_dbgstr_w(out));
396 ok(r==4,"failed: r=%d\n",r);
397 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou,
398 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1 );
399 ok(!lstrcmpW( s_sp001, out),"failed out=[%s]\n", wine_dbgstr_w(out));
400 ok(r==5,"failed: r=%d\n",r);
401 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou1oou,
402 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1, 4, 2 );
403 ok(!lstrcmpW( s_sp001002, out),"failed out=[%s]\n", wine_dbgstr_w(out));
404 ok(r==11,"failed: r=%d\n",r);
405 r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou3oou,
406 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1, 6, 4, 2 );
407 ok(!lstrcmpW( s_sp001sp002, out) ||
408 broken(!lstrcmpW(s_sp001004, out)), /* NT4/Win2k */
409 "failed out=[%s]\n", wine_dbgstr_w(out));
410 ok(r==12,"failed: r=%d\n",r);
411 /* args are not counted the same way with an argument array */
412 {
413 ULONG_PTR args[] = { 6, 4, 2, 5, 3, 1 };
414 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1oou1oou,
415 0, 0, out, sizeof(out)/sizeof(WCHAR), (__ms_va_list *)args );
416 ok(!lstrcmpW(s_sp002sp003, out),"failed out=[%s]\n", wine_dbgstr_w(out));
417 ok(r==13,"failed: r=%d\n",r);
418 r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1oou4oou,
419 0, 0, out, sizeof(out)/sizeof(WCHAR), (__ms_va_list *)args );
420 ok(!lstrcmpW(s_sp002sp001, out),"failed out=[%s]\n", wine_dbgstr_w(out));
421 ok(r==12,"failed: r=%d\n",r);
422 }
423
424 /* change of pace... test the low byte of dwflags */
425
426 /* line feed */
427 r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_lf, 0,
428 0, out, sizeof(out)/sizeof(WCHAR));
429 ok(!lstrcmpW(s_hi_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
430 ok(r==3,"failed: r=%d\n", r);
431
432 /* carriage return line feed */
433 r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_crlf, 0,
434 0, out, sizeof(out)/sizeof(WCHAR));
435 ok(!lstrcmpW(s_hi_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
436 ok(r==3,"failed: r=%d\n", r);
437
438 /* carriage return */
439 r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_cr, 0,
440 0, out, sizeof(out)/sizeof(WCHAR));
441 ok(!lstrcmpW(s_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
442 ok(r==1,"failed: r=%d\n", r);
443
444 /* double carriage return line feed */
445 r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_crcrlf, 0,
446 0, out, sizeof(out)/sizeof(WCHAR));
447 ok(!lstrcmpW(s_2sp, out), "failed out=%s\n", wine_dbgstr_w(out));
448 ok(r==2,"failed: r=%d\n", r);
449 }
450
451 static void test_message_from_string(void)
452 {
453 CHAR out[0x100] = {0};
454 DWORD r;
455 static const char init_buf[] = {'x', 'x', 'x', 'x', 'x', 'x'};
456 static const WCHAR szwTest[] = { 't','e','s','t',0};
457
458 /* the basics */
459 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0,
460 0, out, sizeof(out)/sizeof(CHAR),NULL);
461 ok(!strcmp("test", out),"failed out=[%s]\n",out);
462 ok(r==4,"failed: r=%d\n",r);
463
464 /* null string, crashes on Windows */
465 if (0)
466 {
467 SetLastError(0xdeadbeef);
468 memcpy(out, init_buf, sizeof(init_buf));
469 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
470 0, out, sizeof(out)/sizeof(CHAR), NULL);
471 }
472
473 /* empty string */
474 SetLastError(0xdeadbeef);
475 memcpy(out, init_buf, sizeof(init_buf));
476 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "", 0,
477 0, out, sizeof(out)/sizeof(CHAR), NULL);
478 ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
479 broken(!strcmp("", out)), /* Win9x */
480 "Expected the buffer to be untouched\n");
481 ok(r==0, "succeeded: r=%d\n", r);
482 ok(GetLastError()==0xdeadbeef,
483 "last error %u\n", GetLastError());
484
485 /* format placeholder with no specifier */
486 SetLastError(0xdeadbeef);
487 memcpy(out, init_buf, sizeof(init_buf));
488 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%", 0,
489 0, out, sizeof(out)/sizeof(CHAR), NULL);
490 ok(!memcmp(out, init_buf, sizeof(init_buf)),
491 "Expected the buffer to be untouched\n");
492 ok(r==0, "succeeded: r=%d\n", r);
493 ok(GetLastError()==ERROR_INVALID_PARAMETER,
494 "last error %u\n", GetLastError());
495
496 /* test string with format placeholder with no specifier */
497 SetLastError(0xdeadbeef);
498 memcpy(out, init_buf, sizeof(init_buf));
499 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test%", 0,
500 0, out, sizeof(out)/sizeof(CHAR), NULL);
501 ok(!memcmp(out, init_buf, sizeof(init_buf)),
502 "Expected the buffer to be untouched\n");
503 ok(r==0, "succeeded: r=%d\n", r);
504 ok(GetLastError()==ERROR_INVALID_PARAMETER,
505 "last error %u\n", GetLastError());
506
507 /* insertion with no variadic arguments */
508 SetLastError(0xdeadbeef);
509 memcpy(out, init_buf, sizeof(init_buf));
510 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
511 0, out, sizeof(out)/sizeof(CHAR), NULL);
512 ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
513 broken(!strcmp("%1", out)), /* Win9x */
514 "Expected the buffer to be untouched\n");
515 ok(r==0 ||
516 broken(r==2), /* Win9x */
517 "succeeded: r=%d\n", r);
518 ok(GetLastError()==ERROR_INVALID_PARAMETER ||
519 broken(GetLastError()==0xdeadbeef), /* Win9x */
520 "last error %u\n", GetLastError());
521
522 SetLastError(0xdeadbeef);
523 memcpy(out, init_buf, sizeof(init_buf));
524 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "%1", 0,
525 0, out, sizeof(out)/sizeof(CHAR), NULL);
526 ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
527 broken(!strcmp("%1", out)), /* Win9x */
528 "Expected the buffer to be untouched\n");
529 ok(r==0 ||
530 broken(r==2), /* Win9x */
531 "succeeded: r=%d\n", r);
532 ok(GetLastError()==ERROR_INVALID_PARAMETER ||
533 broken(GetLastError()==0xdeadbeef), /* Win9x */
534 "last error %u\n", GetLastError());
535
536 /* using the format feature */
537 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
538 0, out, sizeof(out)/sizeof(CHAR), "test");
539 ok(!strcmp("test", out),"failed out=[%s]\n",out);
540 ok(r==4,"failed: r=%d\n",r);
541
542 /* no format */
543 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
544 0, out, sizeof(out)/sizeof(CHAR), "test");
545 ok(!strcmp("test", out),"failed out=[%s]\n",out);
546 ok(r==4,"failed: r=%d\n",r);
547
548 /* two pieces */
549 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%2", 0,
550 0, out, sizeof(out)/sizeof(CHAR), "te","st");
551 ok(!strcmp("test", out),"failed out=[%s]\n",out);
552 ok(r==4,"failed: r=%d\n",r);
553
554 /* three pieces */
555 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%3%2%1", 0,
556 0, out, sizeof(out)/sizeof(CHAR), "t","s","e");
557 ok(!strcmp("test", out),"failed out=[%s]\n",out);
558 ok(r==4,"failed: r=%d\n",r);
559
560 /* s doesn't seem to work in format strings */
561 r = doit(FORMAT_MESSAGE_FROM_STRING, "%!s!", 0,
562 0, out, sizeof(out)/sizeof(CHAR), "test");
563 ok(!strcmp("!s!", out),"failed out=[%s]\n",out);
564 ok(r==3,"failed: r=%d\n",r);
565
566 /* ls is unicode */
567 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ls!", 0,
568 0, out, sizeof(out)/sizeof(CHAR), szwTest);
569 ok(!strcmp("test", out),"failed out=[%s]\n",out);
570 ok(r==4,"failed: r=%d\n",r);
571
572 /* S is unicode */
573 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!S!", 0,
574 0, out, sizeof(out)/sizeof(CHAR), szwTest);
575 ok(!strcmp("test", out),"failed out=[%s]\n",out);
576 ok(r==4,"failed: r=%d\n",r);
577
578 /* ws is unicode */
579 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ws!", 0,
580 0, out, sizeof(out)/sizeof(CHAR), szwTest);
581 ok(!strcmp("test", out),"failed out=[%s]\n",out);
582 ok(r==4,"failed: r=%d\n",r);
583
584 /* as characters */
585 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!c!%2!c!%3!c!%1!c!", 0,
586 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
587 ok(!strcmp("test", out),"failed out=[%s]\n",out);
588 ok(r==4,"failed: r=%d\n",r);
589
590 /* lc is unicode */
591 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!lc!%2!lc!%3!lc!%1!lc!", 0,
592 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
593 ok(!strcmp("test", out),"failed out=[%s]\n",out);
594 ok(r==4,"failed: r=%d\n",r);
595
596 /* wc is unicode */
597 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!wc!%2!wc!%3!wc!%1!wc!", 0,
598 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
599 ok(!strcmp("test", out),"failed out=[%s]\n",out);
600 ok(r==4,"failed: r=%d\n",r);
601
602 /* C is unicode */
603 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!C!%2!C!%3!C!%1!C!", 0,
604 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
605 ok(!strcmp("test", out),"failed out=[%s]\n",out);
606 ok(r==4,"failed: r=%d\n",r);
607
608 /* some numbers */
609 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!d!%2!d!%3!d!", 0,
610 0, out, sizeof(out)/sizeof(CHAR), 1,2,3);
611 ok(!strcmp("123", out),"failed out=[%s]\n",out);
612 ok(r==3,"failed: r=%d\n",r);
613
614 /* a single digit with some spacing */
615 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
616 0, out, sizeof(out)/sizeof(CHAR), 1);
617 ok(!strcmp(" 1", out),"failed out=[%s]\n",out);
618 ok(r==4,"failed: r=%d\n",r);
619
620 /* a single digit, left justified */
621 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4d!", 0,
622 0, out, sizeof(out)/sizeof(CHAR), 1);
623 ok(!strcmp("1 ", out),"failed out=[%s]\n",out);
624 ok(r==4,"failed: r=%d\n",r);
625
626 /* two digit decimal number */
627 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
628 0, out, sizeof(out)/sizeof(CHAR), 11);
629 ok(!strcmp(" 11", out),"failed out=[%s]\n",out);
630 ok(r==4,"failed: r=%d\n",r);
631
632 /* a hex number */
633 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4x!", 0,
634 0, out, sizeof(out)/sizeof(CHAR), 11);
635 ok(!strcmp(" b", out),"failed out=[%s]\n",out);
636 ok(r==4,"failed: r=%d\n",r);
637
638 /* a hex number, upper case */
639 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
640 0, out, sizeof(out)/sizeof(CHAR), 11);
641 ok(!strcmp(" B", out),"failed out=[%s]\n",out);
642 ok(r==4,"failed: r=%d\n",r);
643
644 /* a hex number, upper case, left justified */
645 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4X!", 0,
646 0, out, sizeof(out)/sizeof(CHAR), 11);
647 ok(!strcmp("B ", out),"failed out=[%s]\n",out);
648 ok(r==4,"failed: r=%d\n",r);
649
650 /* a long hex number, upper case */
651 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
652 0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
653 ok(!strcmp(" 1AB", out),"failed out=[%s]\n",out);
654 ok(r==4,"failed: r=%d\n",r);
655
656 /* two percent... */
657 r = doit(FORMAT_MESSAGE_FROM_STRING, " %%%% ", 0,
658 0, out, sizeof(out)/sizeof(CHAR));
659 ok(!strcmp(" %% ", out),"failed out=[%s]\n",out);
660 ok(r==4,"failed: r=%d\n",r);
661
662 /* periods are special cases */
663 r = doit(FORMAT_MESSAGE_FROM_STRING, " %.%. %1!d!", 0,
664 0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
665 ok(!strcmp(" .. 427", out),"failed out=[%s]\n",out);
666 ok(r==7,"failed: r=%d\n",r);
667
668 /* %0 ends the line */
669 r = doit(FORMAT_MESSAGE_FROM_STRING, "test%0test", 0,
670 0, out, sizeof(out)/sizeof(CHAR));
671 ok(!strcmp("test", out),"failed out=[%s]\n",out);
672 ok(r==4,"failed: r=%d\n",r);
673
674 /* %! prints an exclamation */
675 r = doit(FORMAT_MESSAGE_FROM_STRING, "yah%!%0 ", 0,
676 0, out, sizeof(out)/sizeof(CHAR));
677 ok(!strcmp("yah!", out),"failed out=[%s]\n",out);
678 ok(r==4,"failed: r=%d\n",r);
679
680 /* %space */
681 r = doit(FORMAT_MESSAGE_FROM_STRING, "% % ", 0,
682 0, out, sizeof(out)/sizeof(CHAR));
683 ok(!strcmp(" ", out),"failed out=[%s]\n",out);
684 ok(r==4,"failed: r=%d\n",r);
685
686 /* %n yields \r\n, %r yields \r, %t yields \t */
687 r = doit(FORMAT_MESSAGE_FROM_STRING, "%n%r%t", 0,
688 0, out, sizeof(out)/sizeof(CHAR));
689 ok(!strcmp("\r\n\r\t", out),"failed out=[%s]\n",out);
690 ok(r==4,"failed: r=%d\n",r);
691
692 /* line feed */
693 r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\n", 0,
694 0, out, sizeof(out)/sizeof(CHAR));
695 ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
696 ok(r==4,"failed: r=%d\n",r);
697
698 /* carriage return line feed */
699 r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\r\n", 0,
700 0, out, sizeof(out)/sizeof(CHAR));
701 ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
702 ok(r==4,"failed: r=%d\n",r);
703
704 /* carriage return */
705 r = doit(FORMAT_MESSAGE_FROM_STRING, "\r", 0,
706 0, out, sizeof(out)/sizeof(CHAR));
707 ok(!strcmp("\r\n", out),"failed out=[%s]\n",out);
708 ok(r==2,"failed: r=%d\n",r);
709
710 /* double carriage return line feed */
711 r = doit(FORMAT_MESSAGE_FROM_STRING, "\r\r\n", 0,
712 0, out, sizeof(out)/sizeof(CHAR));
713 ok(!strcmp("\r\n\r\n", out),"failed out=[%s]\n",out);
714 ok(r==4,"failed: r=%d\n",r);
715
716 /* precision and width */
717
718 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!3s!",
719 0, 0, out, sizeof(out), "t" );
720 ok(!strcmp(" t", out),"failed out=[%s]\n",out);
721 ok(r==3, "failed: r=%d\n",r);
722 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!*s!",
723 0, 0, out, sizeof(out), 4, "t");
724 if (!strcmp("*s",out)) win_skip( "width/precision not supported\n" );
725 else
726 {
727 ok(!strcmp( " t", out),"failed out=[%s]\n",out);
728 ok(r==4,"failed: r=%d\n",r);
729 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4.2u!",
730 0, 0, out, sizeof(out), 3 );
731 ok(!strcmp( " 03", out),"failed out=[%s]\n",out);
732 ok(r==4,"failed: r=%d\n",r);
733 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!*.*u!",
734 0, 0, out, sizeof(out), 5, 3, 1 );
735 ok(!strcmp( " 001", out),"failed out=[%s]\n",out);
736 ok(r==5,"failed: r=%d\n",r);
737 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!*.*u!,%1!*.*u!",
738 0, 0, out, sizeof(out), 5, 3, 1, 4, 2 );
739 ok(!strcmp( " 001, 0002", out),"failed out=[%s]\n",out);
740 ok(r==11,"failed: r=%d\n",r);
741 r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!*.*u!,%3!*.*u!",
742 0, 0, out, sizeof(out), 5, 3, 1, 6, 4, 2 );
743 /* older Win versions marked as broken even though this is arguably the correct behavior */
744 /* but the new (brain-damaged) behavior is specified on MSDN */
745 ok(!strcmp( " 001, 0002", out) ||
746 broken(!strcmp(" 001,000004", out)), /* NT4/Win2k */
747 "failed out=[%s]\n",out);
748 ok(r==12,"failed: r=%d\n",r);
749 /* args are not counted the same way with an argument array */
750 {
751 ULONG_PTR args[] = { 6, 4, 2, 5, 3, 1 };
752 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
753 "%1!*.*u!,%1!*.*u!", 0, 0, out, sizeof(out), (__ms_va_list *)args );
754 ok(!strcmp(" 0002, 00003", out),"failed out=[%s]\n",out);
755 ok(r==13,"failed: r=%d\n",r);
756 r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
757 "%1!*.*u!,%4!*.*u!", 0, 0, out, sizeof(out), (__ms_va_list *)args );
758 ok(!strcmp(" 0002, 001", out),"failed out=[%s]\n",out);
759 ok(r==12,"failed: r=%d\n",r);
760 }
761 }
762
763 /* change of pace... test the low byte of dwflags */
764
765 /* line feed */
766 r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0,
767 0, out, sizeof(out)/sizeof(CHAR));
768 ok(!strcmp("hi ", out) ||
769 broken(!strcmp("hi\r\n", out)), /* Win9x */
770 "failed out=[%s]\n",out);
771 ok(r==3 ||
772 broken(r==4), /* Win9x */
773 "failed: r=%d\n",r);
774
775 /* carriage return line feed */
776 r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0,
777 0, out, sizeof(out)/sizeof(CHAR));
778 ok(!strcmp("hi ", out),"failed out=[%s]\n",out);
779 ok(r==3,"failed: r=%d\n",r);
780
781 /* carriage return */
782 r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0,
783 0, out, sizeof(out)/sizeof(CHAR));
784 ok(!strcmp(" ", out),"failed out=[%s]\n",out);
785 ok(r==1,"failed: r=%d\n",r);
786
787 /* double carriage return line feed */
788 r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0,
789 0, out, sizeof(out)/sizeof(CHAR));
790 ok(!strcmp(" ", out),"failed out=[%s]\n",out);
791 ok(r==2,"failed: r=%d\n",r);
792 }
793
794 static void test_message_ignore_inserts(void)
795 {
796 static const char init_buf[] = {'x', 'x', 'x', 'x', 'x'};
797
798 DWORD ret;
799 CHAR out[256];
800
801 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test", 0, 0, out,
802 sizeof(out)/sizeof(CHAR), NULL);
803 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
804 ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
805
806 /* The %0 escape sequence is handled. */
807 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%0", 0, 0, out,
808 sizeof(out)/sizeof(CHAR), NULL);
809 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
810 ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
811
812 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%0test", 0, 0, out,
813 sizeof(out)/sizeof(CHAR), NULL);
814 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
815 ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
816
817 /* While FormatMessageA returns 0 in this case, no last error code is set. */
818 SetLastError(0xdeadbeef);
819 memcpy(out, init_buf, sizeof(init_buf));
820 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%0test", 0, 0, out,
821 sizeof(out)/sizeof(CHAR), NULL);
822 ok(ret == 0, "Expected FormatMessageA to return 0, got %d\n", ret);
823 ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
824 broken(!strcmp("", out)), /* Win9x */
825 "Expected the output buffer to be untouched\n");
826 ok(GetLastError() == 0xdeadbeef, "Expected GetLastError() to return 0xdeadbeef, got %u\n", GetLastError());
827
828 /* Insert sequences are ignored. */
829 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%1%2!*.*s!%99", 0, 0, out,
830 sizeof(out)/sizeof(CHAR), NULL);
831 ok(ret == 17, "Expected FormatMessageA to return 17, got %d\n", ret);
832 ok(!strcmp("test%1%2!*.*s!%99", out), "Expected output string \"test%%1%%2!*.*s!%%99\", got %s\n", out);
833
834 /* Only the "%n", "%r", and "%t" escape sequences are processed. */
835 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%%% %.%!", 0, 0, out,
836 sizeof(out)/sizeof(CHAR), NULL);
837 ok(ret == 8 ||
838 broken(ret == 7) /* Win9x */,
839 "Expected FormatMessageA to return 8, got %d\n", ret);
840 ok(!strcmp("%%% %.%!", out) ||
841 broken(!strcmp("%%% %.!", out)) /* Win9x */,
842 "Expected output string \"%%%%%% %%.%%!\", got %s\n", out);
843
844 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%n%r%t", 0, 0, out,
845 sizeof(out)/sizeof(CHAR), NULL);
846 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
847 ok(!strcmp("\r\n\r\t", out), "Expected output string \"\\r\\n\\r\\t\", got %s\n", out);
848
849 /* CRLF characters are processed normally. */
850 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "hi\n", 0, 0, out,
851 sizeof(out)/sizeof(CHAR), NULL);
852 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
853 ok(!strcmp("hi\r\n", out), "Expected output string \"hi\\r\\n\", got %s\n", out);
854
855 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "hi\r\n", 0, 0, out,
856 sizeof(out)/sizeof(CHAR), NULL);
857 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
858 ok(!strcmp("hi\r\n", out), "Expected output string \"hi\\r\\n\", got %s\n", out);
859
860 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "\r", 0, 0, out,
861 sizeof(out)/sizeof(CHAR), NULL);
862 ok(ret == 2, "Expected FormatMessageA to return 2, got %d\n", ret);
863 ok(!strcmp("\r\n", out), "Expected output string \"\\r\\n\", got %s\n", out);
864
865 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "\r\r\n", 0, 0, out,
866 sizeof(out)/sizeof(CHAR), NULL);
867 ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
868 ok(!strcmp("\r\n\r\n", out), "Expected output string \"\\r\\n\\r\\n\", got %s\n", out);
869
870 /* The width parameter is handled the same also. */
871 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
872 FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0, 0, out,
873 sizeof(out)/sizeof(CHAR), NULL);
874 ok(!strcmp("hi ", out) ||
875 broken(!strcmp("hi\r\n", out)), /* Win9x */
876 "Expected output string \"hi \", got %s\n", out);
877 ok(ret == 3 ||
878 broken(ret == 4), /* Win9x */
879 "Expected FormatMessageA to return 3, got %d\n", ret);
880
881 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
882 FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0, 0, out,
883 sizeof(out)/sizeof(CHAR), NULL);
884 ok(ret == 3, "Expected FormatMessageA to return 3, got %d\n", ret);
885 ok(!strcmp("hi ", out), "Expected output string \"hi \", got %s\n", out);
886
887 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
888 FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0, 0, out,
889 sizeof(out)/sizeof(CHAR), NULL);
890 ok(ret == 1, "Expected FormatMessageA to return 1, got %d\n", ret);
891 ok(!strcmp(" ", out), "Expected output string \" \", got %s\n", out);
892
893 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
894 FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0, 0, out,
895 sizeof(out)/sizeof(CHAR), NULL);
896 ok(ret == 2, "Expected FormatMessageA to return 2, got %d\n", ret);
897 ok(!strcmp(" ", out), "Expected output string \" \", got %s\n", out);
898 }
899
900 static void test_message_ignore_inserts_wide(void)
901 {
902 static const WCHAR test[] = {'t','e','s','t',0};
903 static const WCHAR empty[] = {0};
904 static const WCHAR fmt_t0[] = {'t','e','s','t','%','0',0};
905 static const WCHAR fmt_t0t[] = {'t','e','s','t','%','0','t','e','s','t',0};
906 static const WCHAR fmt_0t[] = {'%','0','t','e','s','t',0};
907 static const WCHAR fmt_t12oos99[] = {'t','e','s','t','%','1','%','2','!','*','.','*','s','!','%','9','9',0};
908 static const WCHAR fmt_pctspacedot[] = {'%','%','%',' ','%','.','%','!',0};
909 static const WCHAR fmt_nrt[] = {'%','n','%','r','%','t',0};
910 static const WCHAR fmt_hi_lf[] = {'h','i','\n',0};
911 static const WCHAR fmt_hi_crlf[] = {'h','i','\r','\n',0};
912 static const WCHAR fmt_cr[] = {'\r',0};
913 static const WCHAR fmt_crcrlf[] = {'\r','\r','\n',0};
914
915 static const WCHAR s_nrt[] = {'\r','\n','\r','\t',0};
916 static const WCHAR s_hi_crlf[] = {'h','i','\r','\n',0};
917 static const WCHAR s_crlf[] = {'\r','\n',0};
918 static const WCHAR s_crlfcrlf[] = {'\r','\n','\r','\n',0};
919 static const WCHAR s_hi_sp[] = {'h','i',' ',0};
920 static const WCHAR s_sp[] = {' ',0};
921 static const WCHAR s_2sp[] = {' ',' ',0};
922
923 DWORD ret;
924 WCHAR out[256];
925
926 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, test, 0, 0, out,
927 sizeof(out)/sizeof(WCHAR), NULL);
928 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
929 ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
930
931 /* The %0 escape sequence is handled. */
932 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t0, 0, 0, out,
933 sizeof(out)/sizeof(WCHAR), NULL);
934 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
935 ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
936
937 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t0t, 0, 0, out,
938 sizeof(out)/sizeof(WCHAR), NULL);
939 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
940 ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
941
942 /* While FormatMessageA returns 0 in this case, no last error code is set. */
943 SetLastError(0xdeadbeef);
944 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_0t, 0, 0, out,
945 sizeof(out)/sizeof(WCHAR), NULL);
946 ok(ret == 0, "Expected FormatMessageW to return 0, got %d\n", ret);
947 ok(!lstrcmpW(empty, out), "Expected the output buffer to be the empty string, got %s\n", wine_dbgstr_w(out));
948 ok(GetLastError() == 0xdeadbeef, "Expected GetLastError() to return 0xdeadbeef, got %u\n", GetLastError());
949
950 /* Insert sequences are ignored. */
951 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t12oos99, 0, 0, out,
952 sizeof(out)/sizeof(WCHAR), NULL);
953 ok(ret == 17, "Expected FormatMessageW to return 17, got %d\n", ret);
954 ok(!lstrcmpW(fmt_t12oos99, out), "Expected output string \"test%%1%%2!*.*s!%%99\", got %s\n", wine_dbgstr_w(out));
955
956 /* Only the "%n", "%r", and "%t" escape sequences are processed. */
957 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_pctspacedot, 0, 0, out,
958 sizeof(out)/sizeof(WCHAR), NULL);
959 ok(ret == 8, "Expected FormatMessageW to return 8, got %d\n", ret);
960 ok(!lstrcmpW(fmt_pctspacedot, out), "Expected output string \"%%%%%% %%.%%!\", got %s\n", wine_dbgstr_w(out));
961
962 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_nrt, 0, 0, out,
963 sizeof(out)/sizeof(WCHAR), NULL);
964 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
965 ok(!lstrcmpW(s_nrt, out), "Expected output string \"\\r\\n\\r\\t\", got %s\n", wine_dbgstr_w(out));
966
967 /* CRLF characters are processed normally. */
968 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_hi_lf, 0, 0, out,
969 sizeof(out)/sizeof(WCHAR), NULL);
970 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
971 ok(!lstrcmpW(s_hi_crlf, out), "Expected output string \"hi\\r\\n\", got %s\n", wine_dbgstr_w(out));
972
973 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_hi_crlf, 0, 0, out,
974 sizeof(out)/sizeof(WCHAR), NULL);
975 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
976 ok(!lstrcmpW(s_hi_crlf, out), "Expected output string \"hi\\r\\n\", got %s\n", wine_dbgstr_w(out));
977
978 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_cr, 0, 0, out,
979 sizeof(out)/sizeof(WCHAR), NULL);
980 ok(ret == 2, "Expected FormatMessageW to return 2, got %d\n", ret);
981 ok(!lstrcmpW(s_crlf, out), "Expected output string \"\\r\\n\", got %s\n", wine_dbgstr_w(out));
982
983 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_crcrlf, 0, 0, out,
984 sizeof(out)/sizeof(WCHAR), NULL);
985 ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
986 ok(!lstrcmpW(s_crlfcrlf, out), "Expected output string \"\\r\\n\\r\\n\", got %s\n", wine_dbgstr_w(out));
987
988 /* The width parameter is handled the same also. */
989 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
990 FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_lf, 0, 0, out,
991 sizeof(out)/sizeof(WCHAR), NULL);
992 ok(ret == 3, "Expected FormatMessageW to return 3, got %d\n", ret);
993 ok(!lstrcmpW(s_hi_sp, out), "Expected output string \"hi \", got %s\n", wine_dbgstr_w(out));
994
995 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
996 FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_crlf, 0, 0, out,
997 sizeof(out)/sizeof(WCHAR), NULL);
998 ok(ret == 3, "Expected FormatMessageW to return 3, got %d\n", ret);
999 ok(!lstrcmpW(s_hi_sp, out), "Expected output string \"hi \", got %s\n", wine_dbgstr_w(out));
1000
1001 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
1002 FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_cr, 0, 0, out,
1003 sizeof(out)/sizeof(WCHAR), NULL);
1004 ok(ret == 1, "Expected FormatMessageW to return 1, got %d\n", ret);
1005 ok(!lstrcmpW(s_sp, out), "Expected output string \" \", got %s\n", wine_dbgstr_w(out));
1006
1007 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
1008 FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_crcrlf, 0, 0, out,
1009 sizeof(out)/sizeof(WCHAR), NULL);
1010 ok(ret == 2, "Expected FormatMessageW to return 2, got %d\n", ret);
1011 ok(!lstrcmpW(s_2sp, out), "Expected output string \" \", got %s\n", wine_dbgstr_w(out));
1012 }
1013
1014 static void test_message_insufficient_buffer(void)
1015 {
1016 static const char init_buf[] = {'x', 'x', 'x', 'x', 'x'};
1017 static const char expected_buf[] = {'x', 'x', 'x', 'x', 'x'};
1018 DWORD ret;
1019 CHAR out[5];
1020
1021 SetLastError(0xdeadbeef);
1022 memcpy(out, init_buf, sizeof(init_buf));
1023 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, 0, NULL);
1024 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1025 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1026 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1027 GetLastError());
1028 ok(!memcmp(expected_buf, out, sizeof(expected_buf)),
1029 "Expected the buffer to be untouched\n");
1030
1031 SetLastError(0xdeadbeef);
1032 memcpy(out, init_buf, sizeof(init_buf));
1033 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, 1, NULL);
1034 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1035 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1036 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1037 GetLastError());
1038 ok(!memcmp(expected_buf, out, sizeof(expected_buf)),
1039 "Expected the buffer to be untouched\n");
1040
1041 SetLastError(0xdeadbeef);
1042 memcpy(out, init_buf, sizeof(init_buf));
1043 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, sizeof(out)/sizeof(out[0]) - 1, NULL);
1044 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1045 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1046 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1047 GetLastError());
1048 ok(!memcmp(expected_buf, out, sizeof(expected_buf)),
1049 "Expected the buffer to be untouched\n");
1050 }
1051
1052 static void test_message_insufficient_buffer_wide(void)
1053 {
1054 static const WCHAR test[] = {'t','e','s','t',0};
1055 static const WCHAR init_buf[] = {'x', 'x', 'x', 'x', 'x'};
1056 static const WCHAR expected_buf[] = {'x', 'x', 'x', 'x', 'x'};
1057 static const WCHAR broken_buf[] = {0, 'x', 'x', 'x', 'x'};
1058 static const WCHAR broken2_buf[] = {'t','e','s',0,'x'};
1059
1060 DWORD ret;
1061 WCHAR out[5];
1062
1063 SetLastError(0xdeadbeef);
1064 memcpy(out, init_buf, sizeof(init_buf));
1065 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, 0, NULL);
1066 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1067 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1068 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1069 GetLastError());
1070 ok(!memcmp(expected_buf, out, sizeof(expected_buf)),
1071 "Expected the buffer to be untouched\n");
1072
1073 /* Windows Server 2003 and newer report failure but copy a
1074 * truncated string to the buffer for non-zero buffer sizes. */
1075 SetLastError(0xdeadbeef);
1076 memcpy(out, init_buf, sizeof(init_buf));
1077 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, 1, NULL);
1078 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1079 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1080 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1081 GetLastError());
1082 ok(!memcmp(expected_buf, out, sizeof(expected_buf)) ||
1083 broken(!memcmp(broken_buf, out, sizeof(broken_buf))), /* W2K3+ */
1084 "Expected the buffer to be untouched\n");
1085
1086 SetLastError(0xdeadbeef);
1087 memcpy(out, init_buf, sizeof(init_buf));
1088 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, sizeof(out)/sizeof(out[0]) - 1, NULL);
1089 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1090 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1091 "Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
1092 GetLastError());
1093 ok(!memcmp(expected_buf, out, sizeof(expected_buf)) ||
1094 broken(!memcmp(broken2_buf, out, sizeof(broken2_buf))), /* W2K3+ */
1095 "Expected the buffer to be untouched\n");
1096 }
1097
1098 static void test_message_null_buffer(void)
1099 {
1100 DWORD ret, error;
1101
1102 /* Without FORMAT_MESSAGE_ALLOCATE_BUFFER, only the specified buffer size is checked. */
1103 SetLastError(0xdeadbeef);
1104 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 0, NULL);
1105 error = GetLastError();
1106 ok(!ret, "FormatMessageA returned %u\n", ret);
1107 ok(error == ERROR_INSUFFICIENT_BUFFER ||
1108 error == ERROR_INVALID_PARAMETER, /* win9x */
1109 "last error %u\n", error);
1110
1111 SetLastError(0xdeadbeef);
1112 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 1, NULL);
1113 error = GetLastError();
1114 ok(!ret, "FormatMessageA returned %u\n", ret);
1115 ok(error == ERROR_INSUFFICIENT_BUFFER ||
1116 error == ERROR_INVALID_PARAMETER, /* win9x */
1117 "last error %u\n", error);
1118
1119 if (0) /* crashes on Windows */
1120 {
1121 SetLastError(0xdeadbeef);
1122 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 256, NULL);
1123 error = GetLastError();
1124 ok(!ret, "FormatMessageA returned %u\n", ret);
1125 trace("last error %u\n", error);
1126 }
1127
1128 SetLastError(0xdeadbeef);
1129 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);
1130 error = GetLastError();
1131 ok(!ret, "FormatMessageA returned %u\n", ret);
1132 ok(error == ERROR_NOT_ENOUGH_MEMORY ||
1133 error == ERROR_INVALID_PARAMETER, /* win9x */
1134 "last error %u\n", error);
1135
1136 SetLastError(0xdeadbeef);
1137 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 1, NULL);
1138 error = GetLastError();
1139 ok(!ret, "FormatMessageA returned %u\n", ret);
1140 ok(error == ERROR_NOT_ENOUGH_MEMORY ||
1141 error == ERROR_INVALID_PARAMETER, /* win9x */
1142 "last error %u\n", error);
1143
1144 SetLastError(0xdeadbeef);
1145 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 256, NULL);
1146 error = GetLastError();
1147 ok(!ret, "FormatMessageA returned %u\n", ret);
1148 ok(error == ERROR_NOT_ENOUGH_MEMORY ||
1149 error == ERROR_INVALID_PARAMETER, /* win9x */
1150 "last error %u\n", error);
1151 }
1152
1153 static void test_message_null_buffer_wide(void)
1154 {
1155 DWORD ret, error;
1156
1157 SetLastError(0xdeadbeef);
1158 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 0, NULL);
1159 error = GetLastError();
1160 ok(!ret, "FormatMessageW returned %u\n", ret);
1161 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1162
1163 SetLastError(0xdeadbeef);
1164 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 1, NULL);
1165 error = GetLastError();
1166 ok(!ret, "FormatMessageW returned %u\n", ret);
1167 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1168
1169 SetLastError(0xdeadbeef);
1170 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 256, NULL);
1171 error = GetLastError();
1172 ok(!ret, "FormatMessageW returned %u\n", ret);
1173 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1174
1175 SetLastError(0xdeadbeef);
1176 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);
1177 error = GetLastError();
1178 ok(!ret, "FormatMessageW returned %u\n", ret);
1179 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1180
1181 SetLastError(0xdeadbeef);
1182 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 1, NULL);
1183 error = GetLastError();
1184 ok(!ret, "FormatMessageW returned %u\n", ret);
1185 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1186
1187 SetLastError(0xdeadbeef);
1188 ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 256, NULL);
1189 error = GetLastError();
1190 ok(!ret, "FormatMessageW returned %u\n", ret);
1191 ok(error == ERROR_INVALID_PARAMETER, "last error %u\n", error);
1192 }
1193
1194 static void test_message_allocate_buffer(void)
1195 {
1196 DWORD ret;
1197 char *buf;
1198
1199 /* While MSDN suggests that FormatMessageA allocates a buffer whose size is
1200 * the larger of the output string and the requested buffer size, the tests
1201 * will not try to determine the actual size of the buffer allocated, as
1202 * the return value of LocalSize cannot be trusted for the purpose, and it should
1203 * in any case be safe for FormatMessageA to allocate in the manner that
1204 * MSDN suggests. */
1205
1206 SetLastError(0xdeadbeef);
1207 buf = (char *)0xdeadbeef;
1208 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1209 "", 0, 0, (char *)&buf, 0, NULL);
1210 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1211 ok(buf == NULL, "Expected output buffer pointer to be NULL\n");
1212 ok(GetLastError() == 0xdeadbeef,
1213 "Expected last error to be untouched, got %u\n", GetLastError());
1214
1215 buf = (char *)0xdeadbeef;
1216 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1217 "test", 0, 0, (char *)&buf, 0, NULL);
1218 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1219 ok(buf != NULL && buf != (char *)0xdeadbeef,
1220 "Expected output buffer pointer to be valid\n");
1221 if (buf != NULL && buf != (char *)0xdeadbeef)
1222 {
1223 ok(!strcmp("test", buf),
1224 "Expected buffer to contain \"test\", got %s\n", buf);
1225 LocalFree(buf);
1226 }
1227
1228 buf = (char *)0xdeadbeef;
1229 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1230 "test", 0, 0, (char *)&buf, strlen("test"), NULL);
1231 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1232 ok(buf != NULL && buf != (char *)0xdeadbeef,
1233 "Expected output buffer pointer to be valid\n");
1234 if (buf != NULL && buf != (char *)0xdeadbeef)
1235 {
1236 ok(!strcmp("test", buf),
1237 "Expected buffer to contain \"test\", got %s\n", buf);
1238 LocalFree(buf);
1239 }
1240
1241 buf = (char *)0xdeadbeef;
1242 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1243 "test", 0, 0, (char *)&buf, strlen("test") + 1, NULL);
1244 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1245 ok(buf != NULL && buf != (char *)0xdeadbeef,
1246 "Expected output buffer pointer to be valid\n");
1247 if (buf != NULL && buf != (char *)0xdeadbeef)
1248 {
1249 ok(!strcmp("test", buf),
1250 "Expected buffer to contain \"test\", got %s\n", buf);
1251 LocalFree(buf);
1252 }
1253
1254 buf = (char *)0xdeadbeef;
1255 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1256 "test", 0, 0, (char *)&buf, strlen("test") + 2, NULL);
1257 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1258 ok(buf != NULL && buf != (char *)0xdeadbeef,
1259 "Expected output buffer pointer to be valid\n");
1260 if (buf != NULL && buf != (char *)0xdeadbeef)
1261 {
1262 ok(!strcmp("test", buf),
1263 "Expected buffer to contain \"test\", got %s\n", buf);
1264 LocalFree(buf);
1265 }
1266
1267 buf = (char *)0xdeadbeef;
1268 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1269 "test", 0, 0, (char *)&buf, 1024, NULL);
1270 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1271 ok(buf != NULL && buf != (char *)0xdeadbeef,
1272 "Expected output buffer pointer to be valid\n");
1273 if (buf != NULL && buf != (char *)0xdeadbeef)
1274 {
1275 ok(!strcmp("test", buf),
1276 "Expected buffer to contain \"test\", got %s\n", buf);
1277 LocalFree(buf);
1278 }
1279 }
1280
1281 static void test_message_allocate_buffer_wide(void)
1282 {
1283 static const WCHAR empty[] = {0};
1284 static const WCHAR test[] = {'t','e','s','t',0};
1285
1286 DWORD ret;
1287 WCHAR *buf;
1288
1289 /* While MSDN suggests that FormatMessageW allocates a buffer whose size is
1290 * the larger of the output string and the requested buffer size, the tests
1291 * will not try to determine the actual size of the buffer allocated, as
1292 * the return value of LocalSize cannot be trusted for the purpose, and it should
1293 * in any case be safe for FormatMessageW to allocate in the manner that
1294 * MSDN suggests. */
1295
1296 if (0) /* crashes on Windows */
1297 {
1298 buf = (WCHAR *)0xdeadbeef;
1299 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1300 NULL, 0, 0, (WCHAR *)&buf, 0, NULL);
1301 }
1302
1303 SetLastError(0xdeadbeef);
1304 buf = (WCHAR *)0xdeadbeef;
1305 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1306 empty, 0, 0, (WCHAR *)&buf, 0, NULL);
1307 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1308 ok(buf == NULL, "Expected output buffer pointer to be NULL\n");
1309 ok(GetLastError() == 0xdeadbeef,
1310 "Expected last error to be untouched, got %u\n", GetLastError());
1311
1312 buf = (WCHAR *)0xdeadbeef;
1313 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1314 test, 0, 0, (WCHAR *)&buf, 0, NULL);
1315 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1316 ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
1317 "Expected output buffer pointer to be valid\n");
1318 if (buf != NULL && buf != (WCHAR *)0xdeadbeef)
1319 {
1320 ok(!lstrcmpW(test, buf),
1321 "Expected buffer to contain \"test\", got %s\n", wine_dbgstr_w(buf));
1322 LocalFree(buf);
1323 }
1324
1325 buf = (WCHAR *)0xdeadbeef;
1326 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1327 test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR) - 1, NULL);
1328 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1329 ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
1330 "Expected output buffer pointer to be valid\n");
1331 if (buf != NULL && buf != (WCHAR *)0xdeadbeef)
1332 {
1333 ok(!lstrcmpW(test, buf),
1334 "Expected buffer to contain \"test\", got %s\n", wine_dbgstr_w(buf));
1335 LocalFree(buf);
1336 }
1337
1338 buf = (WCHAR *)0xdeadbeef;
1339 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1340 test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR), NULL);
1341 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1342 ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
1343 "Expected output buffer pointer to be valid\n");
1344 if (buf != NULL && buf != (WCHAR *)0xdeadbeef)
1345 {
1346 ok(!lstrcmpW(test, buf),
1347 "Expected buffer to contain \"test\", got %s\n", wine_dbgstr_w(buf));
1348 LocalFree(buf);
1349 }
1350
1351 buf = (WCHAR *)0xdeadbeef;
1352 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1353 test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR) + 1, NULL);
1354 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1355 ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
1356 "Expected output buffer pointer to be valid\n");
1357 if (buf != NULL && buf != (WCHAR *)0xdeadbeef)
1358 {
1359 ok(!lstrcmpW(test, buf),
1360 "Expected buffer to contain \"test\", got %s\n", wine_dbgstr_w(buf));
1361 LocalFree(buf);
1362 }
1363
1364 buf = (WCHAR *)0xdeadbeef;
1365 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1366 test, 0, 0, (WCHAR *)&buf, 1024, NULL);
1367 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1368 ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
1369 "Expected output buffer pointer to be valid\n");
1370 if (buf != NULL && buf != (WCHAR *)0xdeadbeef)
1371 {
1372 ok(!lstrcmpW(test, buf),
1373 "Expected buffer to contain \"test\", got %s\n", wine_dbgstr_w(buf));
1374 LocalFree(buf);
1375 }
1376 }
1377
1378 static void test_message_from_hmodule(void)
1379 {
1380 DWORD ret, error;
1381 HMODULE h;
1382 CHAR out[0x100] = {0};
1383
1384 h = GetModuleHandle("kernel32.dll");
1385 ok(h != 0, "GetModuleHandle failed\n");
1386
1387 /*Test existing messageID; as the message strings from wine's kernel32 differ from windows' kernel32 we don't compare
1388 the strings but only test that FormatMessage doesn't return 0*/
1389 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 7/*=ERROR_ARENA_TRASHED*/,
1390 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
1391 ok(ret != 0, "FormatMessageA returned 0\n");
1392
1393 /* Test a message string with an insertion without passing any variadic arguments. */
1394 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */,
1395 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
1396 ok(ret == 0 ||
1397 broken(ret != 0), /* Win9x */
1398 "FormatMessageA returned non-zero\n");
1399
1400 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
1401 FORMAT_MESSAGE_ARGUMENT_ARRAY, h, 193 /* ERROR_BAD_EXE_FORMAT */,
1402 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
1403 ok(ret == 0 ||
1404 broken(ret != 0), /* Win9x */
1405 "FormatMessageA returned non-zero\n");
1406
1407 /*Test nonexistent messageID with varying language ID's Note: FormatMessageW behaves the same*/
1408 SetLastError(0xdeadbeef);
1409 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
1410 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
1411 error = GetLastError();
1412 ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
1413 ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_FOUND, "last error %u\n", error);
1414
1415 SetLastError(0xdeadbeef);
1416 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
1417 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), out, sizeof(out)/sizeof(CHAR), NULL);
1418 error = GetLastError();
1419 ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
1420 ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_LOADED, "last error %u\n", error);
1421
1422 SetLastError(0xdeadbeef);
1423 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
1424 MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), out, sizeof(out)/sizeof(CHAR), NULL);
1425 error = GetLastError();
1426 ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
1427 ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_LOADED, "last error %u\n", error);
1428
1429 SetLastError(0xdeadbeef);
1430 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
1431 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), out, sizeof(out)/sizeof(CHAR), NULL);
1432 error = GetLastError();
1433 ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
1434 ok(error == ERROR_RESOURCE_LANG_NOT_FOUND ||
1435 error == ERROR_MR_MID_NOT_FOUND ||
1436 error == ERROR_MUI_FILE_NOT_FOUND ||
1437 error == ERROR_MUI_FILE_NOT_LOADED,
1438 "last error %u\n", error);
1439
1440 SetLastError(0xdeadbeef);
1441 ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
1442 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), out, sizeof(out)/sizeof(CHAR), NULL);
1443 error = GetLastError();
1444 ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
1445 ok(error == ERROR_RESOURCE_LANG_NOT_FOUND ||
1446 error == ERROR_MR_MID_NOT_FOUND ||
1447 error == ERROR_MUI_FILE_NOT_FOUND ||
1448 error == ERROR_MUI_FILE_NOT_LOADED,
1449 "last error %u\n", error);
1450 }
1451
1452 static void test_message_invalid_flags(void)
1453 {
1454 static const char init_buf[] = {'x', 'x', 'x', 'x', 'x'};
1455
1456 DWORD ret;
1457 CHAR out[5];
1458 char *ptr;
1459
1460 SetLastError(0xdeadbeef);
1461 memcpy(out, init_buf, sizeof(init_buf));
1462 ret = FormatMessageA(0, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1463 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1464 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1465 "Expected the output buffer to be untouched\n");
1466 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1467 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1468 GetLastError());
1469
1470 SetLastError(0xdeadbeef);
1471 ptr = (char *)0xdeadbeef;
1472 ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER, "test", 0, 0, (char *)&ptr, 0, NULL);
1473 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1474 ok(ptr == NULL ||
1475 broken(ptr == (char *)0xdeadbeef), /* Win9x */
1476 "Expected output pointer to be initialized to NULL, got %p\n", ptr);
1477 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1478 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1479 GetLastError());
1480
1481 SetLastError(0xdeadbeef);
1482 memcpy(out, init_buf, sizeof(init_buf));
1483 ret = FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1484 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1485 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1486 "Expected the output buffer to be untouched\n");
1487 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1488 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1489 GetLastError());
1490
1491 SetLastError(0xdeadbeef);
1492 memcpy(out, init_buf, sizeof(init_buf));
1493 ret = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1494 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1495 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1496 "Expected the output buffer to be untouched\n");
1497 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1498 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1499 GetLastError());
1500
1501 SetLastError(0xdeadbeef);
1502 memcpy(out, init_buf, sizeof(init_buf));
1503 ret = FormatMessageA(FORMAT_MESSAGE_MAX_WIDTH_MASK, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1504 ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
1505 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1506 "Expected the output buffer to be untouched\n");
1507 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1508 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1509 GetLastError());
1510
1511 /* Simultaneously setting FORMAT_MESSAGE_FROM_STRING with other source
1512 * flags is apparently permissible, and FORMAT_MESSAGE_FROM_STRING takes
1513 * precedence in this case. */
1514
1515 memcpy(out, init_buf, sizeof(init_buf));
1516 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_SYSTEM,
1517 "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1518 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1519 ok(!strcmp("test", out),
1520 "Expected the output buffer to be untouched\n");
1521
1522 memcpy(out, init_buf, sizeof(init_buf));
1523 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE,
1524 "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
1525 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1526 ok(!strcmp("test", out),
1527 "Expected the output buffer to be untouched\n");
1528
1529 memcpy(out, init_buf, sizeof(init_buf));
1530 ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE |
1531 FORMAT_MESSAGE_FROM_SYSTEM, "test", 0, 0, out,
1532 sizeof(out)/sizeof(CHAR), NULL);
1533 ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
1534 ok(!strcmp("test", out),
1535 "Expected the output buffer to be untouched\n");
1536 }
1537
1538 static void test_message_invalid_flags_wide(void)
1539 {
1540 static const WCHAR init_buf[] = {'x', 'x', 'x', 'x', 'x'};
1541 static const WCHAR test[] = {'t','e','s','t',0};
1542
1543 DWORD ret;
1544 WCHAR out[5];
1545 WCHAR *ptr;
1546
1547 SetLastError(0xdeadbeef);
1548 memcpy(out, init_buf, sizeof(init_buf));
1549 ret = FormatMessageW(0, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1550 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1551 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1552 "Expected the output buffer to be untouched\n");
1553 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1554 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1555 GetLastError());
1556
1557 SetLastError(0xdeadbeef);
1558 ptr = (WCHAR *)0xdeadbeef;
1559 ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER, test, 0, 0, (WCHAR *)&ptr, 0, NULL);
1560 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1561 ok(ptr == NULL, "Expected output pointer to be initialized to NULL, got %p\n", ptr);
1562 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1563 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1564 GetLastError());
1565
1566 SetLastError(0xdeadbeef);
1567 memcpy(out, init_buf, sizeof(init_buf));
1568 ret = FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1569 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1570 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1571 "Expected the output buffer to be untouched\n");
1572 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1573 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1574 GetLastError());
1575
1576 SetLastError(0xdeadbeef);
1577 memcpy(out, init_buf, sizeof(init_buf));
1578 ret = FormatMessageW(FORMAT_MESSAGE_ARGUMENT_ARRAY, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1579 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1580 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1581 "Expected the output buffer to be untouched\n");
1582 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1583 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1584 GetLastError());
1585
1586 SetLastError(0xdeadbeef);
1587 memcpy(out, init_buf, sizeof(init_buf));
1588 ret = FormatMessageW(FORMAT_MESSAGE_MAX_WIDTH_MASK, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1589 ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
1590 ok(!memcmp(out, init_buf, sizeof(init_buf)),
1591 "Expected the output buffer to be untouched\n");
1592 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1593 "Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
1594 GetLastError());
1595
1596 /* Simultaneously setting FORMAT_MESSAGE_FROM_STRING with other source
1597 * flags is apparently permissible, and FORMAT_MESSAGE_FROM_STRING takes
1598 * precedence in this case. */
1599
1600 memcpy(out, init_buf, sizeof(init_buf));
1601 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_SYSTEM,
1602 test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1603 ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
1604 ok(!lstrcmpW(test, out),
1605 "Expected the output buffer to be untouched\n");
1606
1607 memcpy(out, init_buf, sizeof(init_buf));
1608 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE,
1609 test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
1610 ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
1611 ok(!lstrcmpW(test, out),
1612 "Expected the output buffer to be untouched\n");
1613
1614 memcpy(out, init_buf, sizeof(init_buf));
1615 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE |
1616 FORMAT_MESSAGE_FROM_SYSTEM, test, 0, 0, out,
1617 sizeof(out)/sizeof(WCHAR), NULL);
1618 ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
1619 ok(!lstrcmpW(test, out),
1620 "Expected the output buffer to be untouched\n");
1621 }
1622
1623 START_TEST(format_msg)
1624 {
1625 DWORD ret;
1626
1627 test_message_from_string();
1628 test_message_ignore_inserts();
1629 test_message_insufficient_buffer();
1630 test_message_null_buffer();
1631 test_message_allocate_buffer();
1632 test_message_from_hmodule();
1633 test_message_invalid_flags();
1634
1635 SetLastError(0xdeadbeef);
1636 ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0, 0, NULL, 0, NULL);
1637 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1638 {
1639 win_skip("FormatMessageW is not implemented\n");
1640 return;
1641 }
1642
1643 test_message_from_string_wide();
1644 test_message_ignore_inserts_wide();
1645 test_message_insufficient_buffer_wide();
1646 test_message_null_buffer_wide();
1647 test_message_allocate_buffer_wide();
1648 test_message_invalid_flags_wide();
1649 }