Generate Perl modules defining prototypes for exported functions.
[wine] / dlls / user / resource.c
1 /*
2  * USER resource functions
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include "windef.h"
9 #include "winbase.h"
10 #include "winerror.h"
11 #include "winnls.h"
12 #include "wine/winbase16.h"
13 #include "wine/winuser16.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(resource);
17 DECLARE_DEBUG_CHANNEL(accel);
18
19 /* this is the 8 byte accel struct used in Win32 resources (internal only) */
20 typedef struct
21 {
22     BYTE   fVirt;
23     BYTE   pad0;
24     WORD   key;
25     WORD   cmd;
26     WORD   pad1;
27 } PE_ACCEL, *LPPE_ACCEL;
28
29 /**********************************************************************
30  *                      LoadAccelerators        [USER.177]
31  */
32 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
33 {
34     HRSRC16     hRsrc;
35
36     TRACE_(accel)("%04x %s\n", instance, debugres_a(lpTableName) );
37
38     if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATORA ))) {
39       WARN_(accel)("couldn't find accelerator table resource\n");
40       return 0;
41     }
42
43     TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
44     return LoadResource16(instance,hRsrc);
45 }
46
47 /**********************************************************************
48  *                      LoadAcceleratorsW       (USER32.@)
49  * The image layout seems to look like this (not 100% sure):
50  * 00:  BYTE    type            type of accelerator
51  * 01:  BYTE    pad             (to WORD boundary)
52  * 02:  WORD    event
53  * 04:  WORD    IDval           
54  * 06:  WORD    pad             (to DWORD boundary)
55  */
56 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
57 {
58     HRSRC hRsrc;
59     HACCEL hMem,hRetval=0;
60     DWORD size;
61
62     if (HIWORD(lpTableName))
63         TRACE_(accel)("%p '%s'\n",
64                       (LPVOID)instance, (char *)( lpTableName ) );
65     else
66         TRACE_(accel)("%p 0x%04x\n",
67                        (LPVOID)instance, LOWORD(lpTableName) );
68
69     if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
70     {
71       WARN_(accel)("couldn't find accelerator table resource\n");
72     } else {
73       hMem = LoadResource( instance, hRsrc );
74       size = SizeofResource( instance, hRsrc );
75       if(size>=sizeof(PE_ACCEL))
76       {
77         LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
78         LPACCEL16 accel16;
79         int i,nrofaccells = size/sizeof(PE_ACCEL);
80
81         hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
82         accel16 = (LPACCEL16)GlobalLock16(hRetval);
83         for (i=0;i<nrofaccells;i++) {
84                 accel16[i].fVirt = accel_table[i].fVirt;
85                 accel16[i].key = accel_table[i].key;
86                 accel16[i].cmd = accel_table[i].cmd;
87         }
88         accel16[i-1].fVirt |= 0x80;
89       }
90     }
91     TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
92     return hRetval;
93 }
94
95 /***********************************************************************
96  *              LoadAcceleratorsA   (USER32.@)
97  */
98 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
99 {
100     INT len;
101     LPWSTR uni;
102     HACCEL result = 0;
103
104     if (!HIWORD(lpTableName)) return LoadAcceleratorsW( instance, (LPCWSTR)lpTableName );
105
106     len = MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, NULL, 0 );
107     if ((uni = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
108     {
109         MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, uni, len );
110         result = LoadAcceleratorsW(instance,uni);
111         HeapFree( GetProcessHeap(), 0, uni);
112     }
113     return result;
114 }
115
116 /**********************************************************************
117  *             CopyAcceleratorTableA   (USER32.@)
118  */
119 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
120 {
121   return CopyAcceleratorTableW(src, dst, entries);
122 }
123
124 /**********************************************************************
125  *             CopyAcceleratorTableW   (USER32.@)
126  *
127  * By mortene@pvv.org 980321
128  */
129 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
130                                      INT entries)
131 {
132   int i,xsize;
133   LPACCEL16 accel = (LPACCEL16)GlobalLock16(src);
134   BOOL done = FALSE;
135
136   /* Do parameter checking to avoid the explosions and the screaming
137      as far as possible. */
138   if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel) {
139     WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
140          (LPVOID)src, (LPVOID)dst, entries);
141     return 0;
142   }
143   xsize = GlobalSize16(src)/sizeof(ACCEL16);
144   if (xsize>entries) entries=xsize;
145
146   i=0;
147   while(!done) {
148     /* Spit out some debugging information. */
149     TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
150           i, accel[i].fVirt, accel[i].key, accel[i].cmd);
151
152     /* Copy data to the destination structure array (if dst == NULL,
153        we're just supposed to count the number of entries). */
154     if(dst) {
155       dst[i].fVirt = accel[i].fVirt;
156       dst[i].key = accel[i].key;
157       dst[i].cmd = accel[i].cmd;
158
159       /* Check if we've reached the end of the application supplied
160          accelerator table. */
161       if(i+1 == entries) {
162         /* Turn off the high order bit, just in case. */
163         dst[i].fVirt &= 0x7f;
164         done = TRUE;
165       }
166     }
167
168     /* The highest order bit seems to mark the end of the accelerator
169        resource table, but not always. Use GlobalSize() check too. */
170     if((accel[i].fVirt & 0x80) != 0) done = TRUE;
171
172     i++;
173   }
174
175   return i;
176 }
177
178 /*********************************************************************
179  *                    CreateAcceleratorTableA   (USER32.@)
180  *
181  * By mortene@pvv.org 980321
182  */
183 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
184 {
185   HACCEL        hAccel;
186   LPACCEL16     accel;
187   int           i;
188
189   /* Do parameter checking just in case someone's trying to be
190      funny. */
191   if(cEntries < 1) {
192     WARN_(accel)("Application sent invalid parameters (%p %d).\n",
193          lpaccel, cEntries);
194     SetLastError(ERROR_INVALID_PARAMETER);
195     return (HACCEL)NULL;
196   }
197   FIXME_(accel)("should check that the accelerator descriptions are valid,"
198         " return NULL and SetLastError() if not.\n");
199
200
201   /* Allocate memory and copy the table. */
202   hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
203
204   TRACE_(accel)("handle %x\n", hAccel);
205   if(!hAccel) {
206     ERR_(accel)("Out of memory.\n");
207     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
208     return (HACCEL)NULL;
209   }
210   accel = GlobalLock16(hAccel);
211   for (i=0;i<cEntries;i++) {
212         accel[i].fVirt = lpaccel[i].fVirt;
213         accel[i].key = lpaccel[i].key;
214         accel[i].cmd = lpaccel[i].cmd;
215   }
216   /* Set the end-of-table terminator. */
217   accel[cEntries-1].fVirt |= 0x80;
218
219   TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
220   return hAccel;
221 }
222
223 /*********************************************************************
224  *                    CreateAcceleratorTableW   (USER32.@)
225  *
226  * 
227  */
228 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
229 {
230   HACCEL        hAccel;
231   LPACCEL16     accel;
232   int           i;
233   char          ckey;  
234
235   /* Do parameter checking just in case someone's trying to be
236      funny. */
237   if(cEntries < 1) {
238     WARN_(accel)("Application sent invalid parameters (%p %d).\n",
239          lpaccel, cEntries);
240     SetLastError(ERROR_INVALID_PARAMETER);
241     return (HACCEL)NULL;
242   }
243   FIXME_(accel)("should check that the accelerator descriptions are valid,"
244         " return NULL and SetLastError() if not.\n");
245
246
247   /* Allocate memory and copy the table. */
248   hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
249
250   TRACE_(accel)("handle %x\n", hAccel);
251   if(!hAccel) {
252     ERR_(accel)("Out of memory.\n");
253     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
254     return (HACCEL)NULL;
255   }
256   accel = GlobalLock16(hAccel);
257
258
259   for (i=0;i<cEntries;i++) {
260        accel[i].fVirt = lpaccel[i].fVirt;
261        if( !(accel[i].fVirt & FVIRTKEY) ) {
262           ckey = (char) lpaccel[i].key;
263          if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
264             WARN_(accel)("Error converting ASCII accelerator table to Unicode");
265        }
266        else 
267          accel[i].key = lpaccel[i].key; 
268        accel[i].cmd = lpaccel[i].cmd;
269   }
270
271   /* Set the end-of-table terminator. */
272   accel[cEntries-1].fVirt |= 0x80;
273
274   TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
275   return hAccel;
276 }
277
278 /******************************************************************************
279  * DestroyAcceleratorTable [USER32.@]
280  * Destroys an accelerator table
281  *
282  * NOTES
283  *    By mortene@pvv.org 980321
284  *
285  * PARAMS
286  *    handle [I] Handle to accelerator table
287  *
288  * RETURNS STD
289  */
290 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
291 {
292     return !GlobalFree16(handle); 
293 }
294   
295 /**********************************************************************
296  *     LoadString   (USER.176)
297  */
298 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
299                            LPSTR buffer, INT16 buflen )
300 {
301     HGLOBAL16 hmem;
302     HRSRC16 hrsrc;
303     unsigned char *p;
304     int string_num;
305     int i;
306
307     TRACE("inst=%04x id=%04x buff=%08x len=%d\n",
308           instance, resource_id, (int) buffer, buflen);
309
310     hrsrc = FindResource16( instance, (LPCSTR)((resource_id>>4)+1), RT_STRINGA );
311     if (!hrsrc) return 0;
312     hmem = LoadResource16( instance, hrsrc );
313     if (!hmem) return 0;
314     
315     p = LockResource16(hmem);
316     string_num = resource_id & 0x000f;
317     for (i = 0; i < string_num; i++)
318         p += *p + 1;
319     
320     TRACE("strlen = %d\n", (int)*p );
321     
322     if (buffer == NULL) return *p;
323     i = min(buflen - 1, *p);
324     if (i > 0) {
325         memcpy(buffer, p + 1, i);
326         buffer[i] = '\0';
327     } else {
328         if (buflen > 1) {
329             buffer[0] = '\0';
330             return 0;
331         }
332         WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
333     }
334     FreeResource16( hmem );
335
336     TRACE("'%s' loaded !\n", buffer);
337     return i;
338 }
339
340 /**********************************************************************
341  *      LoadStringW             (USER32.@)
342  */
343 INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
344                             LPWSTR buffer, INT buflen )
345 {
346     HGLOBAL hmem;
347     HRSRC hrsrc;
348     WCHAR *p;
349     int string_num;
350     int i;
351
352     if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
353         resource_id = (UINT)(-((INT)resource_id));
354     TRACE("instance = %04x, id = %04x, buffer = %08x, length = %d\n",
355           instance, (int)resource_id, (int) buffer, buflen);
356
357     /* Use bits 4 - 19 (incremented by 1) as resourceid, mask out 
358      * 20 - 31. */
359     hrsrc = FindResourceW( instance, (LPCWSTR)(((resource_id>>4)&0xffff)+1),
360                              RT_STRINGW );
361     if (!hrsrc) return 0;
362     hmem = LoadResource( instance, hrsrc );
363     if (!hmem) return 0;
364     
365     p = LockResource(hmem);
366     string_num = resource_id & 0x000f;
367     for (i = 0; i < string_num; i++)
368         p += *p + 1;
369     
370     TRACE("strlen = %d\n", (int)*p );
371     
372     if (buffer == NULL) return *p;
373     i = min(buflen - 1, *p);
374     if (i > 0) {
375         memcpy(buffer, p + 1, i * sizeof (WCHAR));
376         buffer[i] = (WCHAR) 0;
377     } else {
378         if (buflen > 1) {
379             buffer[0] = (WCHAR) 0;
380             return 0;
381         }
382 #if 0
383         WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
384 #endif
385     }
386
387     TRACE("%s loaded !\n", debugstr_w(buffer));
388     return i;
389 }
390
391 /**********************************************************************
392  *      LoadStringA     (USER32.@)
393  */
394 INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id,
395                             LPSTR buffer, INT buflen )
396 {
397     INT    retval;
398     LPWSTR wbuf;
399
400     TRACE("instance = %04x, id = %04x, buffer = %08x, length = %d\n",
401           instance, (int)resource_id, (int) buffer, buflen);
402
403     if(buffer == NULL) /* asked size of string */
404         return LoadStringW(instance, resource_id, NULL, 0);
405     
406     wbuf = HeapAlloc(GetProcessHeap(), 0, buflen * sizeof(WCHAR));
407     if(!wbuf)
408         return 0;
409
410     retval = LoadStringW(instance, resource_id, wbuf, buflen);
411     if(retval != 0)
412     {
413         retval = WideCharToMultiByte(CP_ACP, 0, wbuf, retval, buffer, buflen - 1, NULL, NULL);
414         buffer[retval] = 0;
415         TRACE("%s loaded !\n", debugstr_a(buffer));
416     }
417     else buffer[0] = 0;    /* no check of buflen here */
418     HeapFree( GetProcessHeap(), 0, wbuf );
419
420     return retval;
421 }