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

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

basic support for VIO console command line apps added + FormatMessage addition

File size: 16.5 KB
Line 
1/* $Id: message.cpp,v 1.13 2000-10-20 11:46:47 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 if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
226 /* Ignore inserts, except for '%0' - maybe more? */
227 if (*f == '0') {
228 eos = TRUE;
229 f++;
230 continue;
231 }
232 else {
233 ADD_TO_T('%');
234 continue;
235 }
236 }
237
238 switch (*f)
239 {
240 case '1': case '2': case '3': case '4': case '5':
241 case '6': case '7': case '8': case '9':
242 insertnr=*f-'0';
243 switch (f[1])
244 {
245 case '0':case '1':case '2':case '3':
246 case '4':case '5':case '6':case '7':
247 case '8':case '9':
248 f++;
249 insertnr=insertnr*10+*f-'0';
250 f++;
251 break;
252
253 default:
254 f++;
255 break;
256 }
257
258 if (*f=='!')
259 {
260 f++;
261 if (NULL!=(x=strchr(f,'!')))
262 {
263 *x='\0';
264 fmtstr = (char*)HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
265 sprintf(fmtstr,"%%%s",f);
266 f=x+1;
267 }
268 else
269 {
270 fmtstr = (char*)HeapAlloc(GetProcessHeap(),0,strlen(f));
271 sprintf(fmtstr,"%%%s",f);
272 f+=strlen(f); /*at \0*/
273 }
274 }
275 else
276 if(!args)
277 break;
278 else
279 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
280
281 if (args)
282 {
283 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
284 argliststart=args+insertnr-1;
285 else
286 argliststart=(*(DWORD**)args)+insertnr-1;
287
288 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0])
289 sprintfbuf = (char*)HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
290 else
291 sprintfbuf = (char*)HeapAlloc(GetProcessHeap(),0,100);
292
293 /* CMF - This makes a BIG assumption about va_list */
294 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
295 x=sprintfbuf;
296 while (*x)
297 {
298 ADD_TO_T(*x++);
299 }
300
301 HeapFree(GetProcessHeap(),0,sprintfbuf);
302 }
303 else
304 {
305 /* NULL args - copy formatstr
306 * (probably wrong)
307 */
308 while ((lastf<f)&&(*lastf))
309 {
310 ADD_TO_T(*lastf++);
311 }
312 }
313
314 HeapFree(GetProcessHeap(),0,fmtstr);
315 break;
316
317 case 'n':
318 ADD_TO_T('\r');
319 ADD_TO_T('\n');
320 f++;
321 break;
322
323 case '0':
324 eos = TRUE;
325 f++;
326 break;
327
328 default:ADD_TO_T(*f++)
329 break;
330 }
331 } else
332 { /* '\n' or '\r' gets mapped to "\r\n" */
333 if(*f == '\n' || *f == '\r')
334 {
335 ADD_TO_T('\r');
336 ADD_TO_T('\n');
337 if(*f++ == '\r' && *f == '\n')
338 f++;
339 } else
340 {
341 ADD_TO_T(*f++);
342 }
343 }
344 }
345 *t='\0';
346 }
347
348 talloced = strlen(target)+1;
349 if (nSize && talloced<nSize)
350 {
351 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
352 }
353
354 //TRACE("-- %s\n",debugstr_a(target));
355
356 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
357 {
358 /* nSize is the MINIMUM size */
359 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced);
360 memcpy(*(LPSTR*)lpBuffer,target,talloced);
361 }
362 else {
363 strncpy(lpBuffer,target,nSize);
364 lpBuffer[nSize-1] = 0;
365 }
366
367 HeapFree(GetProcessHeap(),0,target);
368 if (from)
369 HeapFree(GetProcessHeap(),0,from);
370
371 dprintf(("gives: %s", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
372 *(LPSTR*)lpBuffer : lpBuffer));
373
374 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
375 strlen(*(LPSTR*)lpBuffer):
376 strlen(lpBuffer);
377}
378#undef ADD_TO_T
379
380
381/***********************************************************************
382 * FormatMessage32W (KERNEL32.138)
383 */
384DWORD WINAPI FormatMessageW(DWORD dwFlags,
385 LPCVOID lpSource,
386 DWORD dwMessageId,
387 DWORD dwLanguageId,
388 LPWSTR lpBuffer,
389 DWORD nSize,
390 LPDWORD args /* va_list *args */ )
391{
392/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
393 LPSTR target,t;
394 DWORD talloced;
395 LPSTR from,f;
396 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
397 BOOL eos = FALSE;
398
399 dprintf(("KERNEL32: FormatMessageW(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh,%08xh)\n",
400 dwFlags,
401 lpSource,
402 dwMessageId,
403 dwLanguageId,
404 lpBuffer,
405 nSize,
406 args));
407
408 if (width)
409 dprintf(("KERNEL32: FormatMessageW - line wrapping not supported.\n"));
410
411 from = NULL;
412 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
413 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
414
415 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
416 {
417 /* gather information from system message tables ... */
418 from = (char*)HeapAlloc( GetProcessHeap(),0,200 );
419 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
420 }
421
422 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
423 {
424 INT bufsize;
425
426//SvL/MN: VACPPWIN uses message ids > 64k!!
427#ifndef __WIN32OS2__
428 dwMessageId &= 0xFFFF;
429#endif
430 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
431 if (bufsize)
432 {
433 from = (char*)HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
434 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
435 }
436 }
437
438 target = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
439 t = target;
440 talloced= 100;
441
442#define ADD_TO_T(c) \
443 *t++=c;\
444 if (t-target == talloced) {\
445 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
446 t = target+talloced;\
447 talloced*=2;\
448 }
449
450 if (from) {
451 f=from;
452 while (*f && !eos) {
453 if (*f=='%') {
454 int insertnr;
455 char *fmtstr,*sprintfbuf,*x;
456 DWORD *argliststart;
457
458 fmtstr = NULL;
459 f++;
460 if (!*f) {
461 ADD_TO_T('%');
462 continue;
463 }
464
465 if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
466 /* Ignore inserts, except for '%0' - maybe more? */
467 if (*f == '0') {
468 eos = TRUE;
469 f++;
470 continue;
471 }
472 else {
473 ADD_TO_T('%');
474 continue;
475 }
476 }
477
478 switch (*f) {
479 case '1':case '2':case '3':case '4':case '5':
480 case '6':case '7':case '8':case '9':
481 insertnr=*f-'0';
482 switch (f[1]) {
483 case '0':case '1':case '2':case '3':
484 case '4':case '5':case '6':case '7':
485 case '8':case '9':
486 f++;
487 insertnr=insertnr*10+*f-'0';
488 f++;
489 break;
490 default:
491 f++;
492 break;
493 }
494 if (*f=='!') {
495 f++;
496 if (NULL!=(x=strchr(f,'!')))
497 {
498 *x='\0';
499 fmtstr=(char*)HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
500 sprintf(fmtstr,"%%%s",f);
501 f=x+1;
502 } else {
503 fmtstr=(char*)HeapAlloc(GetProcessHeap(),0,strlen(f));
504 sprintf(fmtstr,"%%%s",f);
505 f+=strlen(f); /*at \0*/
506 }
507 } else
508 if(!args)
509 break;
510 else
511 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
512 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
513 argliststart=args+insertnr-1;
514 else
515 argliststart=(*(DWORD**)args)+insertnr-1;
516
517 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) {
518 DWORD xarr[3];
519
520 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
521 /* possible invalid pointers */
522 xarr[1]=*(argliststart+1);
523 xarr[2]=*(argliststart+2);
524 sprintfbuf=(char*)HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR)argliststart[0])*2+1);
525
526 /* CMF - This makes a BIG assumption about va_list */
527 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
528 } else {
529 sprintfbuf=(char*)HeapAlloc(GetProcessHeap(),0,100);
530
531 /* CMF - This makes a BIG assumption about va_list */
532 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
533 }
534 x=sprintfbuf;
535 while (*x) {
536 ADD_TO_T(*x++);
537 }
538 HeapFree(GetProcessHeap(),0,sprintfbuf);
539 HeapFree(GetProcessHeap(),0,fmtstr);
540 break;
541 case 'n':
542 ADD_TO_T('\r');
543 ADD_TO_T('\n');
544 f++;
545 break;
546 case '0':
547 eos = TRUE;
548 f++;
549 break;
550 default:ADD_TO_T(*f++)
551 break;
552
553 }
554 } else
555 { /* '\n' or '\r' gets mapped to "\r\n" */
556 if(*f == '\n' || *f == '\r')
557 {
558 ADD_TO_T('\r');
559 ADD_TO_T('\n');
560 if(*f++ == '\r' && *f == '\n')
561 f++;
562 } else
563 {
564 ADD_TO_T(*f++);
565 }
566 }
567 }
568 *t='\0';
569 }
570 talloced = strlen(target)+1;
571 if (nSize && talloced<nSize)
572 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
573 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
574 /* nSize is the MINIMUM size */
575 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced*2+2);
576 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
577 } else
578 lstrcpynAtoW(lpBuffer,target,nSize);
579 HeapFree(GetProcessHeap(),0,target);
580 if (from) HeapFree(GetProcessHeap(),0,from);
581 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
582 lstrlenW(*(LPWSTR*)lpBuffer):
583 lstrlenW(lpBuffer);
584}
585#undef ADD_TO_T
586
587
Note: See TracBrowser for help on using the repository browser.