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