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

Last change on this file since 4440 was 4440, checked in by sandervl, 25 years ago

console, pe loader + FormatMessage fixes

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