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