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

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

strncpy call changes + language api updates/fixes

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