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