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

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

Fix: FormatMessageA fixed, A/W potential memoryleak fixed.

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