cryptdlg: Add missing encoding info to the German resource file.
[wine] / dlls / user32 / resource.c
1 /*
2  * USER resource functions
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winternl.h"
28 #include "winnls.h"
29 #include "wine/winbase16.h"
30 #include "wine/winuser16.h"
31 #include "wownt32.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(resource);
35 WINE_DECLARE_DEBUG_CHANNEL(accel);
36
37 /* this is the 8 byte accel struct used in Win32 resources (internal only) */
38 typedef struct
39 {
40     WORD   fVirt;
41     WORD   key;
42     WORD   cmd;
43     WORD   pad;
44 } PE_ACCEL, *LPPE_ACCEL;
45
46 /**********************************************************************
47  *                      LoadAccelerators        [USER.177]
48  */
49 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
50 {
51     HRSRC16     hRsrc;
52
53     TRACE_(accel)("%04x %s\n", instance, debugstr_a(lpTableName) );
54
55     if (!(hRsrc = FindResource16( instance, lpTableName, (LPSTR)RT_ACCELERATOR ))) {
56       WARN_(accel)("couldn't find accelerator table resource\n");
57       return 0;
58     }
59
60     TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
61     return LoadResource16(instance,hRsrc);
62 }
63
64 /**********************************************************************
65  *                      LoadAcceleratorsW       (USER32.@)
66  * The image layout seems to look like this (not 100% sure):
67  * 00:  WORD    type            type of accelerator
68  * 02:  WORD    event
69  * 04:  WORD    IDval
70  * 06:  WORD    pad             (to DWORD boundary)
71  */
72 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
73 {
74     HRSRC hRsrc;
75     HACCEL hMem;
76     HACCEL16 hRetval=0;
77     DWORD size;
78
79     if (HIWORD(lpTableName))
80         TRACE_(accel)("%p '%s'\n", instance, (const char *)( lpTableName ) );
81     else
82         TRACE_(accel)("%p 0x%04x\n", instance, LOWORD(lpTableName) );
83
84     if (!(hRsrc = FindResourceW( instance, lpTableName, (LPWSTR)RT_ACCELERATOR )))
85     {
86       WARN_(accel)("couldn't find accelerator table resource\n");
87     } else {
88       hMem = LoadResource( instance, hRsrc );
89       size = SizeofResource( instance, hRsrc );
90       if(size>=sizeof(PE_ACCEL))
91       {
92         LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
93         LPACCEL16 accel16;
94         int i,nrofaccells = size/sizeof(PE_ACCEL);
95
96         hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
97         accel16 = (LPACCEL16)GlobalLock16(hRetval);
98         for (i=0;i<nrofaccells;i++) {
99           accel16[i].fVirt = accel_table[i].fVirt & 0x7f;
100           accel16[i].key = accel_table[i].key;
101           if( !(accel16[i].fVirt & FVIRTKEY) )
102             accel16[i].key &= 0x00ff;
103           accel16[i].cmd = accel_table[i].cmd;
104         }
105         accel16[i-1].fVirt |= 0x80;
106       }
107     }
108     TRACE_(accel)("returning HACCEL %p\n", hRsrc);
109     return HACCEL_32(hRetval);
110 }
111
112 /***********************************************************************
113  *              LoadAcceleratorsA   (USER32.@)
114  */
115 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
116 {
117     INT len;
118     LPWSTR uni;
119     HACCEL result = 0;
120
121     if (!HIWORD(lpTableName)) return LoadAcceleratorsW( instance, (LPCWSTR)lpTableName );
122
123     len = MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, NULL, 0 );
124     if ((uni = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
125     {
126         MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, uni, len );
127         result = LoadAcceleratorsW(instance,uni);
128         HeapFree( GetProcessHeap(), 0, uni);
129     }
130     return result;
131 }
132
133 /**********************************************************************
134  *             CopyAcceleratorTableA   (USER32.@)
135  */
136 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
137 {
138   return CopyAcceleratorTableW(src, dst, entries);
139 }
140
141 /**********************************************************************
142  *             CopyAcceleratorTableW   (USER32.@)
143  *
144  * By mortene@pvv.org 980321
145  */
146 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
147                                      INT entries)
148 {
149   int i,xsize;
150   LPACCEL16 accel = (LPACCEL16)GlobalLock16(HACCEL_16(src));
151   BOOL done = FALSE;
152
153   /* Do parameter checking to avoid the explosions and the screaming
154      as far as possible. */
155   if((dst && (entries < 1)) || (src == NULL) || !accel) {
156     WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
157          src, dst, entries);
158     return 0;
159   }
160   xsize = GlobalSize16(HACCEL_16(src))/sizeof(ACCEL16);
161   if (xsize<entries) entries=xsize;
162
163   i=0;
164   while(!done) {
165     /* Spit out some debugging information. */
166     TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
167           i, accel[i].fVirt, accel[i].key, accel[i].cmd);
168
169     /* Copy data to the destination structure array (if dst == NULL,
170        we're just supposed to count the number of entries). */
171     if(dst) {
172       dst[i].fVirt = accel[i].fVirt&0x7f;
173       dst[i].key = accel[i].key;
174       dst[i].cmd = accel[i].cmd;
175
176       /* Check if we've reached the end of the application supplied
177          accelerator table. */
178       if(i+1 == entries)
179         done = TRUE;
180     }
181
182     /* The highest order bit seems to mark the end of the accelerator
183        resource table, but not always. Use GlobalSize() check too. */
184     if((accel[i].fVirt & 0x80) != 0) done = TRUE;
185
186     i++;
187   }
188
189   return i;
190 }
191
192 /*********************************************************************
193  *                    CreateAcceleratorTableA   (USER32.@)
194  *
195  * By mortene@pvv.org 980321
196  */
197 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
198 {
199   HACCEL        hAccel;
200   LPACCEL16     accel;
201   int           i;
202
203   /* Do parameter checking just in case someone's trying to be
204      funny. */
205   if(cEntries < 1) {
206     WARN_(accel)("Application sent invalid parameters (%p %d).\n",
207          lpaccel, cEntries);
208     SetLastError(ERROR_INVALID_PARAMETER);
209     return NULL;
210   }
211
212   /* Allocate memory and copy the table. */
213   hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
214
215   TRACE_(accel)("handle %p\n", hAccel);
216   if(!hAccel) {
217     ERR_(accel)("Out of memory.\n");
218     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
219     return NULL;
220   }
221   accel = GlobalLock16(HACCEL_16(hAccel));
222   for (i=0;i<cEntries;i++) {
223     accel[i].fVirt = lpaccel[i].fVirt&0x7f;
224     accel[i].key = lpaccel[i].key;
225     if( !(accel[i].fVirt & FVIRTKEY) )
226       accel[i].key &= 0x00ff;
227     accel[i].cmd = lpaccel[i].cmd;
228   }
229   /* Set the end-of-table terminator. */
230   accel[cEntries-1].fVirt |= 0x80;
231
232   TRACE_(accel)("Allocated accelerator handle %p with %d entries\n", hAccel,cEntries);
233   return hAccel;
234 }
235
236 /*********************************************************************
237  *                    CreateAcceleratorTableW   (USER32.@)
238  *
239  *
240  */
241 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
242 {
243   HACCEL        hAccel;
244   LPACCEL16     accel;
245   int           i;
246   char          ckey;
247
248   /* Do parameter checking just in case someone's trying to be
249      funny. */
250   if(cEntries < 1) {
251     WARN_(accel)("Application sent invalid parameters (%p %d).\n",
252          lpaccel, cEntries);
253     SetLastError(ERROR_INVALID_PARAMETER);
254     return NULL;
255   }
256
257   /* Allocate memory and copy the table. */
258   hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
259
260   TRACE_(accel)("handle %p\n", hAccel);
261   if(!hAccel) {
262     ERR_(accel)("Out of memory.\n");
263     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
264     return NULL;
265   }
266   accel = GlobalLock16(HACCEL_16(hAccel));
267
268
269   for (i=0;i<cEntries;i++) {
270        accel[i].fVirt = lpaccel[i].fVirt&0x7f;
271        if( !(accel[i].fVirt & FVIRTKEY) ) {
272           ckey = (char) lpaccel[i].key;
273          if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
274             WARN_(accel)("Error converting ASCII accelerator table to Unicode\n");
275        }
276        else
277          accel[i].key = lpaccel[i].key;
278        accel[i].cmd = lpaccel[i].cmd;
279   }
280
281   /* Set the end-of-table terminator. */
282   accel[cEntries-1].fVirt |= 0x80;
283
284   TRACE_(accel)("Allocated accelerator handle %p\n", hAccel);
285   return hAccel;
286 }
287
288 /******************************************************************************
289  * DestroyAcceleratorTable [USER32.@]
290  * Destroys an accelerator table
291  *
292  * NOTES
293  *    By mortene@pvv.org 980321
294  *
295  * PARAMS
296  *    handle [I] Handle to accelerator table
297  *
298  * RETURNS
299  *    Success: TRUE
300  *    Failure: FALSE
301  */
302 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
303 {
304     if( !handle )
305         return FALSE;
306     return !GlobalFree16(HACCEL_16(handle));
307 }
308
309 /**********************************************************************
310  *     LoadString   (USER.176)
311  */
312 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
313                            LPSTR buffer, INT16 buflen )
314 {
315     HGLOBAL16 hmem;
316     HRSRC16 hrsrc;
317     unsigned char *p;
318     int string_num;
319     int i;
320
321     TRACE("inst=%04x id=%04x buff=%p len=%d\n",
322           instance, resource_id, buffer, buflen);
323
324     hrsrc = FindResource16( instance, MAKEINTRESOURCEA((resource_id>>4)+1), (LPSTR)RT_STRING );
325     if (!hrsrc) return 0;
326     hmem = LoadResource16( instance, hrsrc );
327     if (!hmem) return 0;
328
329     p = LockResource16(hmem);
330     string_num = resource_id & 0x000f;
331     for (i = 0; i < string_num; i++)
332         p += *p + 1;
333
334     TRACE("strlen = %d\n", (int)*p );
335
336     if (buffer == NULL) return *p;
337     i = min(buflen - 1, *p);
338     if (i > 0) {
339         memcpy(buffer, p + 1, i);
340         buffer[i] = '\0';
341     } else {
342         if (buflen > 1) {
343             buffer[0] = '\0';
344             return 0;
345         }
346         WARN("Don't know why caller gave buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
347     }
348     FreeResource16( hmem );
349
350     TRACE("'%s' loaded !\n", buffer);
351     return i;
352 }
353
354 /**********************************************************************
355  *      LoadStringW             (USER32.@)
356  */
357 INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
358                             LPWSTR buffer, INT buflen )
359 {
360     HGLOBAL hmem;
361     HRSRC hrsrc;
362     WCHAR *p;
363     int string_num;
364     int i;
365
366     TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
367           instance, resource_id, buffer, buflen);
368
369     if(buffer == NULL)
370         return 0;
371
372     /* Use loword (incremented by 1) as resourceid */
373     hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
374                            (LPWSTR)RT_STRING );
375     if (!hrsrc) return 0;
376     hmem = LoadResource( instance, hrsrc );
377     if (!hmem) return 0;
378
379     p = LockResource(hmem);
380     string_num = resource_id & 0x000f;
381     for (i = 0; i < string_num; i++)
382         p += *p + 1;
383
384     TRACE("strlen = %d\n", (int)*p );
385
386     /*if buflen == 0, then return a read-only pointer to the resource itself in buffer
387     it is assumed that buffer is actually a (LPWSTR *) */
388     if(buflen == 0)
389     {
390         *((LPWSTR *)buffer) = p + 1;
391         return *p;
392     }
393
394     i = min(buflen - 1, *p);
395     if (i > 0) {
396         memcpy(buffer, p + 1, i * sizeof (WCHAR));
397         buffer[i] = 0;
398     } else {
399         if (buflen > 1) {
400             buffer[0] = 0;
401             return 0;
402         }
403     }
404
405     TRACE("%s loaded !\n", debugstr_w(buffer));
406     return i;
407 }
408
409 /**********************************************************************
410  *      LoadStringA     (USER32.@)
411  */
412 INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen )
413 {
414     HGLOBAL hmem;
415     HRSRC hrsrc;
416     DWORD retval = 0;
417
418     TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
419           instance, resource_id, buffer, buflen);
420
421     if (!buflen) return -1;
422
423     /* Use loword (incremented by 1) as resourceid */
424     if ((hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
425                                 (LPWSTR)RT_STRING )) &&
426         (hmem = LoadResource( instance, hrsrc )))
427     {
428         const WCHAR *p = LockResource(hmem);
429         unsigned int id = resource_id & 0x000f;
430
431         while (id--) p += *p + 1;
432
433         RtlUnicodeToMultiByteN( buffer, buflen - 1, &retval, p + 1, *p * sizeof(WCHAR) );
434     }
435     buffer[retval] = 0;
436     TRACE("returning %s\n", debugstr_a(buffer));
437     return retval;
438 }
439
440 /**********************************************************************
441  *      GetGuiResources (USER32.@)
442  */
443 DWORD WINAPI GetGuiResources( HANDLE hProcess, DWORD uiFlags )
444 {
445     static BOOL warn = TRUE;
446
447     if (warn) {
448         FIXME("(%p,%x): stub\n",hProcess,uiFlags);
449        warn = FALSE;
450     }
451
452     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
453     return 0;
454 }