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

Last change on this file since 424 was 424, checked in by phaller, 26 years ago

Fix: FormatMessageAW fixed. Do not mix ODIN's heap functions with VAC heap functions ...

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