source: trunk/src/kernel32/message.cpp

Last change on this file was 10185, checked in by sandervl, 22 years ago

Updates

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