source: trunk/src/kernel32/message.cpp@ 1792

Last change on this file since 1792 was 1792, checked in by achimha, 26 years ago

Christoph's LoadMessage fix for linefeeds at the end

File size: 15.4 KB
Line 
1/* $Id: message.cpp,v 1.8 1999-11-21 13:59:36 achimha Exp $ */
2
3/*
4 * Win32 message API functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen (ported WINE code)
7 *
8 * Original WINE code (loader\resource.c)
9 * WINE level: 991031
10 *
11 * Resources
12 *
13 * Copyright 1993 Robert J. Amstadt
14 * Copyright 1995 Alexandre Julliard
15 *
16 * Project Odin Software License can be found in LICENSE.TXT
17 *
18 */
19#include <os2win.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <stdarg.h>
24#include "unicode.h"
25#include "heap.h"
26#include "heapstring.h"
27
28typedef VOID (*WVSPRINTFAPROC)(LPSTR,LPCSTR,va_list);
29WVSPRINTFAPROC wvsprintfAProc = NULL;
30
31BOOL LoadwvsprintfA(VOID)
32{
33 //CB: load wvsprintfA dynamic to avoid problems with crosslinked DLL's
34 if (!wvsprintfAProc)
35 {
36 HMODULE hUser32 = LoadLibraryA("USER32.DLL");
37
38 wvsprintfAProc = (WVSPRINTFAPROC)GetProcAddress(hUser32,"wvsprintfA");
39 FreeLibrary(hUser32);
40 }
41
42 return wvsprintfAProc != NULL;
43}
44
45//******************************************************************************
46//******************************************************************************
47int LoadMessageA(HINSTANCE instance, UINT id, WORD lang,
48 LPSTR buffer, int buflen )
49{
50 HGLOBAL hmem;
51 HRSRC hrsrc;
52 BYTE *p;
53 int nrofentries,i,slen;
54 struct _subentry {
55 DWORD firstentry;
56 DWORD lastentry;
57 DWORD offset;
58 } *se;
59 struct _stringentry {
60 WORD len;
61 WORD unknown;
62 CHAR str[1];
63 } *stre;
64
65 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
66 hrsrc = FindResourceW(instance,(LPWSTR)1,RT_MESSAGELISTW);
67 if (!hrsrc) return 0;
68 hmem = LoadResource(instance, hrsrc);
69 if (!hmem) return 0;
70
71 p = (BYTE *)LockResource(hmem);
72 nrofentries = *(DWORD*)p;
73 stre = NULL;
74 se = (struct _subentry*)(p+4);
75 for (i=nrofentries;i--;) {
76 if ((id>=se->firstentry) && (id<=se->lastentry)) {
77 stre = (struct _stringentry*)(p+se->offset);
78 id -= se->firstentry;
79 break;
80 }
81 se++;
82 }
83 if (!stre)
84 return 0;
85 for (i=id;i--;) {
86 if (!(slen=stre->len))
87 return 0;
88 stre = (struct _stringentry*)(((char*)stre)+slen);
89 }
90 slen=stre->len;
91
92 i = min(buflen - 1, slen);
93 if (buffer == NULL)
94 return slen; /* different to LoadString */
95 if (i>0) {
96 strncpy(buffer,stre->str,i);
97 buffer[i]=0;
98 } else {
99 if (buflen>1) {
100 buffer[0]=0;
101 return 0;
102 }
103 }
104 return i;
105}
106
107/**********************************************************************
108 * LoadMessage32W (internal)
109 */
110int LoadMessageW(HINSTANCE instance, UINT id, WORD lang,
111 LPWSTR buffer, int buflen )
112{
113 INT retval;
114 LPSTR buffer2 = NULL;
115 if (buffer) buffer2 = (char *)HeapAlloc(GetProcessHeap(), 0, buflen );
116 retval = LoadMessageA(instance,id,lang,buffer2,buflen);
117 if (buffer)
118 {
119 AsciiToUnicode(buffer2, buffer);
120 HeapFree(GetProcessHeap(), 0, buffer2);
121 }
122 return retval;
123}
124
125
126/***********************************************************************
127 * FormatMessage32A (KERNEL32.138)
128 * FIXME: missing wrap,FROM_SYSTEM message-loading,
129 */
130DWORD WIN32API FormatMessageA(DWORD dwFlags,
131 LPCVOID lpSource,
132 DWORD dwMessageId,
133 DWORD dwLanguageId,
134 LPSTR lpBuffer,
135 DWORD nSize,
136 LPDWORD args /* va_list *args */)
137{
138/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
139 LPSTR target,
140 t;
141 DWORD talloced;
142 LPSTR from,
143 f;
144 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
145 BOOL eos = FALSE;
146
147 dprintf(("KERNEL32: FormatMessageA(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh,%08xh)\n",
148 dwFlags,
149 lpSource,
150 dwMessageId,
151 dwLanguageId,
152 lpBuffer,
153 nSize,
154 args));
155
156 if (width)
157 dprintf(("KERNEL32: FormatMessageA - line wrapping not supported.\n"));
158
159 from = NULL;
160 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
161 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
162
163 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
164 {
165 from = (char*)HeapAlloc( GetProcessHeap(),0,200 );
166 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
167 }
168
169 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
170 {
171 INT bufsize;
172
173 dwMessageId &= 0xFFFF;
174 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
175 if (bufsize)
176 {
177 from = (char*)HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
178 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
179 }
180 }
181
182 target = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
183 t = target;
184 talloced= 100;
185
186#define ADD_TO_T(c) \
187 *t++=c;\
188 if (t-target == talloced) {\
189 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
190 t = target+talloced;\
191 talloced*=2;\
192 }
193
194 if (from)
195 {
196 f=from;
197
198 while (*f && !eos)
199 {
200 if (*f=='%')
201 {
202 int insertnr;
203 char *fmtstr,
204 *sprintfbuf,
205 *x,
206 *lastf;
207 DWORD *argliststart;
208
209 fmtstr = NULL;
210 lastf = f;
211 f++;
212
213 if (!*f)
214 {
215 ADD_TO_T('%');
216 continue;
217 }
218
219 switch (*f)
220 {
221 case '1': case '2': case '3': case '4': case '5':
222 case '6': case '7': case '8': case '9':
223 insertnr=*f-'0';
224 switch (f[1])
225 {
226 case '0':case '1':case '2':case '3':
227 case '4':case '5':case '6':case '7':
228 case '8':case '9':
229 f++;
230 insertnr=insertnr*10+*f-'0';
231 f++;
232 break;
233
234 default:
235 f++;
236 break;
237 }
238
239 if (*f=='!')
240 {
241 f++;
242 if (NULL!=(x=strchr(f,'!')))
243 {
244 *x='\0';
245 fmtstr = (char*)HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
246 sprintf(fmtstr,"%%%s",f);
247 f=x+1;
248 }
249 else
250 {
251 fmtstr = (char*)HeapAlloc(GetProcessHeap(),0,strlen(f));
252 sprintf(fmtstr,"%%%s",f);
253 f+=strlen(f); /*at \0*/
254 }
255 }
256 else
257 if(!args)
258 break;
259 else
260 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
261
262 if (args)
263 {
264 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
265 argliststart=args+insertnr-1;
266 else
267 argliststart=(*(DWORD**)args)+insertnr-1;
268
269 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0])
270 sprintfbuf = (char*)HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
271 else
272 sprintfbuf = (char*)HeapAlloc(GetProcessHeap(),0,100);
273
274 /* CMF - This makes a BIG assumption about va_list */
275 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
276 x=sprintfbuf;
277 while (*x)
278 {
279 ADD_TO_T(*x++);
280 }
281
282 HeapFree(GetProcessHeap(),0,sprintfbuf);
283 }
284 else
285 {
286 /* NULL args - copy formatstr
287 * (probably wrong)
288 */
289 while ((lastf<f)&&(*lastf))
290 {
291 ADD_TO_T(*lastf++);
292 }
293 }
294
295 HeapFree(GetProcessHeap(),0,fmtstr);
296 break;
297
298 case 'n':
299 ADD_TO_T('\r');
300 ADD_TO_T('\n');
301 f++;
302 break;
303
304 case '0':
305 eos = TRUE;
306 f++;
307 break;
308
309 default:ADD_TO_T(*f++)
310 break;
311 }
312 } else
313 { /* '\n' or '\r' gets mapped to "\r\n" */
314 if(*f == '\n' || *f == '\r')
315 {
316 ADD_TO_T('\r');
317 ADD_TO_T('\n');
318 if(*f++ == '\r' && *f == '\n')
319 f++;
320 } else
321 {
322 ADD_TO_T(*f++);
323 }
324 }
325 }
326 *t='\0';
327 }
328
329 talloced = strlen(target)+1;
330 if (nSize && talloced<nSize)
331 {
332 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
333 }
334
335 //TRACE("-- %s\n",debugstr_a(target));
336
337 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
338 {
339 /* nSize is the MINIMUM size */
340 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced);
341 memcpy(*(LPSTR*)lpBuffer,target,talloced);
342 }
343 else
344 strncpy(lpBuffer,target,nSize);
345
346 HeapFree(GetProcessHeap(),0,target);
347 if (from)
348 HeapFree(GetProcessHeap(),0,from);
349
350 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
351 strlen(*(LPSTR*)lpBuffer):
352 strlen(lpBuffer);
353}
354#undef ADD_TO_T
355
356
357/***********************************************************************
358 * FormatMessage32W (KERNEL32.138)
359 */
360DWORD WINAPI FormatMessageW(DWORD dwFlags,
361 LPCVOID lpSource,
362 DWORD dwMessageId,
363 DWORD dwLanguageId,
364 LPWSTR lpBuffer,
365 DWORD nSize,
366 LPDWORD args /* va_list *args */ )
367{
368/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
369 LPSTR target,t;
370 DWORD talloced;
371 LPSTR from,f;
372 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
373 BOOL eos = FALSE;
374
375 dprintf(("KERNEL32: FormatMessageW(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh,%08xh)\n",
376 dwFlags,
377 lpSource,
378 dwMessageId,
379 dwLanguageId,
380 lpBuffer,
381 nSize,
382 args));
383
384 if (width)
385 dprintf(("KERNEL32: FormatMessageW - line wrapping not supported.\n"));
386
387 from = NULL;
388 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
389 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
390
391 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
392 {
393 /* gather information from system message tables ... */
394 from = (char*)HeapAlloc( GetProcessHeap(),0,200 );
395 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
396 }
397
398 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
399 {
400 INT bufsize;
401
402 dwMessageId &= 0xFFFF;
403 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
404 if (bufsize)
405 {
406 from = (char*)HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
407 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
408 }
409 }
410
411 target = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
412 t = target;
413 talloced= 100;
414
415#define ADD_TO_T(c) \
416 *t++=c;\
417 if (t-target == talloced) {\
418 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
419 t = target+talloced;\
420 talloced*=2;\
421 }
422
423 if (from) {
424 f=from;
425 while (*f && !eos) {
426 if (*f=='%') {
427 int insertnr;
428 char *fmtstr,*sprintfbuf,*x;
429 DWORD *argliststart;
430
431 fmtstr = NULL;
432 f++;
433 if (!*f) {
434 ADD_TO_T('%');
435 continue;
436 }
437 switch (*f) {
438 case '1':case '2':case '3':case '4':case '5':
439 case '6':case '7':case '8':case '9':
440 insertnr=*f-'0';
441 switch (f[1]) {
442 case '0':case '1':case '2':case '3':
443 case '4':case '5':case '6':case '7':
444 case '8':case '9':
445 f++;
446 insertnr=insertnr*10+*f-'0';
447 f++;
448 break;
449 default:
450 f++;
451 break;
452 }
453 if (*f=='!') {
454 f++;
455 if (NULL!=(x=strchr(f,'!')))
456 {
457 *x='\0';
458 fmtstr=(char*)HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
459 sprintf(fmtstr,"%%%s",f);
460 f=x+1;
461 } else {
462 fmtstr=(char*)HeapAlloc(GetProcessHeap(),0,strlen(f));
463 sprintf(fmtstr,"%%%s",f);
464 f+=strlen(f); /*at \0*/
465 }
466 } else
467 if(!args)
468 break;
469 else
470 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
471 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
472 argliststart=args+insertnr-1;
473 else
474 argliststart=(*(DWORD**)args)+insertnr-1;
475
476 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) {
477 DWORD xarr[3];
478
479 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
480 /* possible invalid pointers */
481 xarr[1]=*(argliststart+1);
482 xarr[2]=*(argliststart+2);
483 sprintfbuf=(char*)HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR)argliststart[0])*2+1);
484
485 /* CMF - This makes a BIG assumption about va_list */
486 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
487 } else {
488 sprintfbuf=(char*)HeapAlloc(GetProcessHeap(),0,100);
489
490 /* CMF - This makes a BIG assumption about va_list */
491 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
492 }
493 x=sprintfbuf;
494 while (*x) {
495 ADD_TO_T(*x++);
496 }
497 HeapFree(GetProcessHeap(),0,sprintfbuf);
498 HeapFree(GetProcessHeap(),0,fmtstr);
499 break;
500 case 'n':
501 ADD_TO_T('\r');
502 ADD_TO_T('\n');
503 f++;
504 break;
505 case '0':
506 eos = TRUE;
507 f++;
508 break;
509 default:ADD_TO_T(*f++)
510 break;
511
512 }
513 } else
514 { /* '\n' or '\r' gets mapped to "\r\n" */
515 if(*f == '\n' || *f == '\r')
516 {
517 ADD_TO_T('\r');
518 ADD_TO_T('\n');
519 if(*f++ == '\r' && *f == '\n')
520 f++;
521 } else
522 {
523 ADD_TO_T(*f++);
524 }
525 }
526 }
527 *t='\0';
528 }
529 talloced = strlen(target)+1;
530 if (nSize && talloced<nSize)
531 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
532 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
533 /* nSize is the MINIMUM size */
534 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced*2+2);
535 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
536 } else
537 lstrcpynAtoW(lpBuffer,target,nSize);
538 HeapFree(GetProcessHeap(),0,target);
539 if (from) HeapFree(GetProcessHeap(),0,from);
540 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
541 lstrlenW(*(LPWSTR*)lpBuffer):
542 lstrlenW(lpBuffer);
543}
544#undef ADD_TO_T
545
546
Note: See TracBrowser for help on using the repository browser.