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
RevLine 
[10185]1/* $Id: message.cpp,v 1.14 2003-07-28 11:35:31 sandervl Exp $ */
[100]2
[4]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)
[1792]9 * WINE level: 991031
[4]10 *
11 * Resources
12 *
13 * Copyright 1993 Robert J. Amstadt
14 * Copyright 1995 Alexandre Julliard
[1242]15 *
16 * Project Odin Software License can be found in LICENSE.TXT
17 *
[4]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"
[424]25#include "heap.h"
26#include "heapstring.h"
[4]27
[4502]28#define DBG_LOCALLOG DBG_message
[2802]29#include "dbglocal.h"
30
[2147]31typedef VOID (* WIN32API WVSPRINTFAPROC)(LPSTR,LPCSTR,va_list);
[1792]32WVSPRINTFAPROC wvsprintfAProc = NULL;
[424]33
[1792]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
[4]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;
[10185]62 MESSAGE_RESOURCE_ENTRY *stre;
[4]63
64 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
[1792]65 hrsrc = FindResourceW(instance,(LPWSTR)1,RT_MESSAGELISTW);
[4]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)) {
[10185]76 stre = (PMESSAGE_RESOURCE_ENTRY)(p+se->offset);
[4]77 id -= se->firstentry;
78 break;
79 }
80 se++;
81 }
82 if (!stre)
83 return 0;
84 for (i=id;i--;) {
[10185]85 if (!(slen=stre->Length))
[4]86 return 0;
[10185]87 stre = (PMESSAGE_RESOURCE_ENTRY)(((char*)stre)+slen);
[4]88 }
[10185]89 slen=stre->Length;
[4]90
91 i = min(buflen - 1, slen);
92 if (buffer == NULL)
93 return slen; /* different to LoadString */
94 if (i>0) {
[10185]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;
[4]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
[424]127
[4]128/***********************************************************************
129 * FormatMessage32A (KERNEL32.138)
130 * FIXME: missing wrap,FROM_SYSTEM message-loading,
131 */
[424]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;
[1792]147 BOOL eos = FALSE;
[4]148
[424]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));
[4]157
[424]158 if (width)
159 dprintf(("KERNEL32: FormatMessageA - line wrapping not supported.\n"));
[4]160
[424]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 {
[10185]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 }
[424]177 }
[4]178
[424]179 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
180 {
181 INT bufsize;
[157]182
[4440]183//SvL/MN: VACPPWIN uses message ids > 64k!!
184#ifndef __WIN32OS2__
[424]185 dwMessageId &= 0xFFFF;
[4440]186#endif
[424]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 }
[157]194
[424]195 target = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
196 t = target;
197 talloced= 100;
198
[4]199#define ADD_TO_T(c) \
[424]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 }
[4]206
[424]207 if (from)
208 {
209 f=from;
[4]210
[1792]211 while (*f && !eos)
[424]212 {
213 if (*f=='%')
214 {
215 int insertnr;
216 char *fmtstr,
217 *sprintfbuf,
218 *x,
219 *lastf;
220 DWORD *argliststart;
[4]221
[424]222 fmtstr = NULL;
223 lastf = f;
224 f++;
[4]225
[424]226 if (!*f)
227 {
228 ADD_TO_T('%');
229 continue;
230 }
[4]231
[4502]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
[424]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;
[157]259
[424]260 default:
261 f++;
262 break;
263 }
[157]264
[424]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
[1792]295 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0])
[424]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 */
[1792]301 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
[424]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':
[1792]325 ADD_TO_T('\r');
[424]326 ADD_TO_T('\n');
327 f++;
328 break;
329
330 case '0':
[1792]331 eos = TRUE;
[424]332 f++;
333 break;
334
335 default:ADD_TO_T(*f++)
336 break;
337 }
[1792]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 }
[424]350 }
351 }
352 *t='\0';
353 }
354
[157]355 talloced = strlen(target)+1;
356 if (nSize && talloced<nSize)
357 {
358 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
359 }
360
[424]361 //TRACE("-- %s\n",debugstr_a(target));
362
[157]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 }
[3804]369 else {
[157]370 strncpy(lpBuffer,target,nSize);
[3804]371 lpBuffer[nSize-1] = 0;
372 }
[157]373
374 HeapFree(GetProcessHeap(),0,target);
[424]375 if (from)
376 HeapFree(GetProcessHeap(),0,from);
[157]377
[4502]378 dprintf(("gives: %s", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
379 *(LPSTR*)lpBuffer : lpBuffer));
380
[157]381 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
[424]382 strlen(*(LPSTR*)lpBuffer):
383 strlen(lpBuffer);
[4]384}
385#undef ADD_TO_T
386
[424]387
[4]388/***********************************************************************
389 * FormatMessage32W (KERNEL32.138)
390 */
[424]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;
[1792]404 BOOL eos = FALSE;
[4]405
[424]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));
[4]414
[424]415 if (width)
416 dprintf(("KERNEL32: FormatMessageW - line wrapping not supported.\n"));
[4]417
[424]418 from = NULL;
419 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
420 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
[157]421
[424]422 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
423 {
[10185]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 }
[424]434 }
[4]435
[424]436 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
437 {
438 INT bufsize;
439
[4440]440//SvL/MN: VACPPWIN uses message ids > 64k!!
441#ifndef __WIN32OS2__
[424]442 dwMessageId &= 0xFFFF;
[4440]443#endif
[424]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
[4]456#define ADD_TO_T(c) \
[424]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 }
[4]463
[424]464 if (from) {
465 f=from;
[1792]466 while (*f && !eos) {
[424]467 if (*f=='%') {
468 int insertnr;
469 char *fmtstr,*sprintfbuf,*x;
470 DWORD *argliststart;
[4]471
[424]472 fmtstr = NULL;
473 f++;
474 if (!*f) {
475 ADD_TO_T('%');
476 continue;
477 }
[4502]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
[424]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,'!')))
[4]511 {
512 *x='\0';
[424]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;
[4]530
[1792]531 if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) {
[424]532 DWORD xarr[3];
[4]533
[424]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);
[4]539
[424]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);
[4]544
[424]545 /* CMF - This makes a BIG assumption about va_list */
[1792]546 if (LoadwvsprintfA()) wvsprintfAProc(sprintfbuf,fmtstr,(va_list)argliststart);
[424]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':
[1792]556 ADD_TO_T('\r');
[424]557 ADD_TO_T('\n');
558 f++;
559 break;
560 case '0':
[1792]561 eos = TRUE;
[424]562 f++;
563 break;
564 default:ADD_TO_T(*f++)
565 break;
[4]566
[1792]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 }
[424]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);
[4]598}
[424]599#undef ADD_TO_T
[4]600
[1792]601
Note: See TracBrowser for help on using the repository browser.