- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[wine] / loader / ne / convert.c
1 /*
2  * PE->NE resource conversion functions
3  *
4  * Copyright 1998 Ulrich Weigand
5  */
6
7 #include "wine/winuser16.h"
8 #include "module.h"
9 #include "debug.h"
10 #include "debugtools.h"
11
12 /**********************************************************************
13  *          ConvertDialog32To16   (KERNEL.615)
14  */
15 VOID WINAPI ConvertDialog32To16( LPVOID dialog32, DWORD size, LPVOID dialog16 )
16 {
17     LPVOID p = dialog32;
18     WORD nbItems, data, dialogEx;
19     DWORD style;
20
21     style = *((DWORD *)dialog16)++ = *((DWORD *)p)++;
22     dialogEx = (style == 0xffff0001);  /* DIALOGEX resource */
23     if (dialogEx)
24     {
25         *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
26         *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
27         style = *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
28     }
29     else
30         ((DWORD *)p)++; /* exStyle ignored in 16-bit standard dialog */
31
32     nbItems = *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++;
33     *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
34     *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
35     *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
36     *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
37
38     /* Transfer menu name */
39     switch (*((WORD *)p))
40     {
41     case 0x0000:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
42     case 0xffff:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff; 
43                   *((WORD *)dialog16)++ = *((WORD *)p)++; break;
44     default:      lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
45                   ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
46                   ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
47                   break;
48     }
49
50     /* Transfer class name */
51     switch (*((WORD *)p))
52     {
53     case 0x0000:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
54     case 0xffff:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff; 
55                   *((WORD *)dialog16)++ = *((WORD *)p)++; break;
56     default:      lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
57                   ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
58                   ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
59                   break;
60     }
61
62     /* Transfer window caption */
63     lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
64     ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
65     ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
66
67     /* Transfer font info */
68     if (style & DS_SETFONT)
69     {
70         *((WORD *)dialog16)++ = *((WORD *)p)++;  /* pointSize */
71         if (dialogEx)
72         {
73             *((WORD *)dialog16)++ = *((WORD *)p)++; /* weight */
74             *((WORD *)dialog16)++ = *((WORD *)p)++; /* italic */
75         }
76         lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );  /* faceName */
77         ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
78         ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
79     }
80
81     /* Transfer dialog items */
82     while (nbItems)
83     {
84         /* align on DWORD boundary (32-bit only) */
85         p = (LPVOID)((((int)p) + 3) & ~3);
86
87         if (dialogEx)
88         {
89             *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
90             *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
91             *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
92         }
93         else
94         {
95             style = *((DWORD *)p)++; /* save style */
96             ((DWORD *)p)++;          /* ignore exStyle */
97         }
98
99         *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
100         *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
101         *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
102         *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
103
104         if (dialogEx)
105             *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* ID */
106         else
107         {
108             *((WORD *)dialog16)++ = *((WORD *)p)++; /* ID */
109             *((DWORD *)dialog16)++ = style;  /* style from above */
110         }
111
112         /* Transfer class name */
113         switch (*((WORD *)p))
114         {
115         case 0x0000:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
116         case 0xffff:  ((WORD *)p)++; 
117                       *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++; break;
118         default:      lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
119                       ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
120                       ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
121                       break;
122         }
123
124         /* Transfer window name */
125         switch (*((WORD *)p))
126         {
127         case 0x0000:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
128         case 0xffff:  ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff; 
129                       *((WORD *)dialog16)++ = *((WORD *)p)++; break;
130         default:      lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
131                       ((LPSTR)dialog16) += lstrlen32A( (LPSTR)dialog16 ) + 1;
132                       ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
133                       break;
134         }
135        
136         /* Transfer data */
137         data = *((WORD *)p)++; 
138         if (dialogEx)
139             *((WORD *)dialog16)++ = data;
140         else
141             *((BYTE *)dialog16)++ = (BYTE)data;
142
143         if (data) 
144         {
145             memcpy( dialog16, p, data );
146             (LPSTR)dialog16 += data;
147             (LPSTR)p += data;
148         }
149
150         /* Next item */
151         nbItems--;
152     }
153 }
154
155 /**********************************************************************
156  *          GetDialog32Size   (KERNEL.618)
157  */
158 WORD WINAPI GetDialog32Size( LPVOID dialog32 )
159 {
160     LPVOID p = dialog32;
161     WORD nbItems, data, dialogEx;
162     DWORD style;
163
164     style = *((DWORD *)p)++;
165     dialogEx = (style == 0xffff0001);  /* DIALOGEX resource */
166     if (dialogEx)
167     {
168         ((DWORD *)p)++; /* helpID */
169         ((DWORD *)p)++; /* exStyle */
170         style = *((DWORD *)p)++; /* style */
171     }
172     else
173         ((DWORD *)p)++; /* exStyle */
174
175     nbItems = *((WORD *)p)++;
176     ((WORD *)p)++; /* x */
177     ((WORD *)p)++; /* y */
178     ((WORD *)p)++; /* cx */
179     ((WORD *)p)++; /* cy */
180
181     /* Skip menu name */
182     switch (*((WORD *)p))
183     {
184     case 0x0000:  ((WORD *)p)++; break;
185     case 0xffff:  ((WORD *)p) += 2; break;
186     default:      ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1; break;
187     }
188
189     /* Skip class name */
190     switch (*((WORD *)p))
191     {
192     case 0x0000:  ((WORD *)p)++; break;
193     case 0xffff:  ((WORD *)p) += 2; break;
194     default:      ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1; break;
195     }
196
197     /* Skip window caption */
198     ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1; 
199
200     /* Skip font info */
201     if (style & DS_SETFONT)
202     {
203         ((WORD *)p)++;  /* pointSize */
204         if (dialogEx)
205         {
206             ((WORD *)p)++; /* weight */
207             ((WORD *)p)++; /* italic */
208         }
209         ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;  /* faceName */
210     }
211
212     /* Skip dialog items */
213     while (nbItems)
214     {
215         /* align on DWORD boundary */
216         p = (LPVOID)((((int)p) + 3) & ~3);
217
218         if (dialogEx)
219         {
220             ((DWORD *)p)++; /* helpID */
221             ((DWORD *)p)++; /* exStyle */
222             ((DWORD *)p)++; /* style */
223         }
224         else
225         {
226             ((DWORD *)p)++; /* style */
227             ((DWORD *)p)++; /* exStyle */
228         }
229
230         ((WORD *)p)++; /* x */
231         ((WORD *)p)++; /* y */
232         ((WORD *)p)++; /* cx */
233         ((WORD *)p)++; /* cy */
234
235         if (dialogEx)
236             ((DWORD *)p)++; /* ID */
237         else
238             ((WORD *)p)++; /* ID */
239
240         /* Skip class name */
241         switch (*((WORD *)p))
242         {
243         case 0x0000:  ((WORD *)p)++; break;
244         case 0xffff:  ((WORD *)p) += 2; break;
245         default:      ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1; break;
246         }
247
248         /* Skip window name */
249         switch (*((WORD *)p))
250         {
251         case 0x0000:  ((WORD *)p)++; break;
252         case 0xffff:  ((WORD *)p) += 2; break;
253         default:      ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1; break;
254         }
255        
256         /* Skip data */
257         data = *((WORD *)p)++; 
258         (LPSTR)p += data;
259
260         /* Next item */
261         nbItems--;
262     }
263
264     return (WORD)((LPSTR)p - (LPSTR)dialog32);
265 }
266
267 /**********************************************************************
268  *          ConvertMenu32To16   (KERNEL.616)
269  */
270 VOID WINAPI ConvertMenu32To16( LPVOID menu32, DWORD size, LPVOID menu16 )
271 {
272     LPVOID p = menu32;
273     WORD version, headersize, flags, level = 1;
274
275     version = *((WORD *)menu16)++ = *((WORD *)p)++;
276     headersize = *((WORD *)menu16)++ = *((WORD *)p)++;
277     if ( headersize )
278     {
279         memcpy( menu16, p, headersize );
280         ((LPSTR)menu16) += headersize;
281         ((LPSTR)p) += headersize;
282     }
283
284     while ( level )
285         if ( version == 0 )  /* standard */
286         {
287             flags = *((WORD *)menu16)++ = *((WORD *)p)++;
288             if ( !(flags & MF_POPUP) )
289                 *((WORD *)menu16)++ = *((WORD *)p)++;  /* ID */
290             else
291                 level++;
292        
293             lstrcpyWtoA( (LPSTR)menu16, (LPWSTR)p );
294             ((LPSTR)menu16) += lstrlen32A( (LPSTR)menu16 ) + 1;
295             ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
296
297             if ( flags & MF_END )
298                 level--;
299         }
300         else  /* extended */
301         {
302             *((DWORD *)menu16)++ = *((DWORD *)p)++;  /* fType */
303             *((DWORD *)menu16)++ = *((DWORD *)p)++;  /* fState */
304             *((WORD *)menu16)++ = (WORD)*((DWORD *)p)++; /* ID */
305             flags = *((BYTE *)menu16)++ = (BYTE)*((WORD *)p)++;  
306        
307             lstrcpyWtoA( (LPSTR)menu16, (LPWSTR)p );
308             ((LPSTR)menu16) += lstrlen32A( (LPSTR)menu16 ) + 1;
309             ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
310
311             /* align on DWORD boundary (32-bit only) */
312             p = (LPVOID)((((int)p) + 3) & ~3);
313
314             /* If popup, transfer helpid */
315             if ( flags & 1)
316             {
317                 *((DWORD *)menu16)++ = *((DWORD *)p)++;
318                 level++;
319             }
320
321             if ( flags & MF_END )
322                 level--;
323         }
324 }
325
326 /**********************************************************************
327  *          GetMenu32Size   (KERNEL.617)
328  */
329 WORD WINAPI GetMenu32Size( LPVOID menu32 )
330 {
331     LPVOID p = menu32;
332     WORD version, headersize, flags, level = 1;
333
334     version = *((WORD *)p)++;
335     headersize = *((WORD *)p)++;
336     ((LPSTR)p) += headersize;
337
338     while ( level )
339         if ( version == 0 )  /* standard */
340         {
341             flags = *((WORD *)p)++;
342             if ( !(flags & MF_POPUP) )
343                 ((WORD *)p)++;  /* ID */
344             else
345                 level++;
346        
347             ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
348
349             if ( flags & MF_END )
350                 level--;
351         }
352         else  /* extended */
353         {
354             ((DWORD *)p)++; /* fType */
355             ((DWORD *)p)++; /* fState */
356             ((DWORD *)p)++; /* ID */
357             flags = *((WORD *)p)++; 
358        
359             ((LPWSTR)p) += lstrlen32W( (LPWSTR)p ) + 1;
360
361             /* align on DWORD boundary (32-bit only) */
362             p = (LPVOID)((((int)p) + 3) & ~3);
363
364             /* If popup, skip helpid */
365             if ( flags & 1)
366             {
367                 ((DWORD *)p)++;
368                 level++;
369             }
370
371             if ( flags & MF_END )
372                 level--;
373         }
374
375     return (WORD)((LPSTR)p - (LPSTR)menu32);
376 }
377
378 /**********************************************************************
379  *          ConvertAccelerator32To16
380  */
381 VOID ConvertAccelerator32To16( LPVOID acc32, DWORD size, LPVOID acc16 )
382 {
383     int type;
384
385     do
386     {
387         /* Copy type */
388         type = *((BYTE *)acc16)++ = *((BYTE *)acc32)++;
389         /* Skip padding */
390         ((BYTE *)acc32)++;
391         /* Copy event and IDval */
392         *((WORD *)acc16)++ = *((WORD *)acc32)++;
393         *((WORD *)acc16)++ = *((WORD *)acc32)++;
394         /* Skip padding */
395         ((WORD *)acc32)++;
396
397     } while ( !( type & 0x80 ) );
398 }
399
400 /**********************************************************************
401  *          NE_LoadPEResource
402  */
403 HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size )
404 {
405     HGLOBAL16 handle;
406
407     TRACE( resource, "module=%04x type=%04x\n", pModule->self, type );
408     if (!pModule || !bits || !size) return 0;
409
410     handle = GlobalAlloc16( 0, size );
411    
412     switch (type)
413     {
414     case RT_MENU16:
415         ConvertMenu32To16( bits, size, GlobalLock16( handle ) );
416         break;
417
418     case RT_DIALOG16:
419         ConvertDialog32To16( bits, size, GlobalLock16( handle ) );
420         break;
421
422     case RT_ACCELERATOR16:
423         ConvertAccelerator32To16( bits, size, GlobalLock16( handle ) );
424         break;
425
426     case RT_STRING16:
427         FIXME( resource, "not yet implemented!\n" );
428         /* fall through */
429
430     default:
431         memcpy( GlobalLock16( handle ), bits, size );
432         break;
433     }
434
435     return handle;
436 }
437
438 /**********************************************************************
439  *          NE_FreePEResource
440  */
441 BOOL16 NE_FreePEResource( NE_MODULE *pModule, HGLOBAL16 handle )
442 {
443     GlobalFree16( handle );
444     return 0;
445 }
446