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

Last change on this file since 1242 was 1242, checked in by sandervl, 26 years ago

EB's GetFullPathNameW fix

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