msvcr90: Added _encoded_null() implementation.
[wine] / dlls / user32 / resource.c
1 /*
2  * USER resource functions
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995, 2009 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/debug.h"
30 #include "user_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(resource);
33 WINE_DECLARE_DEBUG_CHANNEL(accel);
34
35 /* this is the 8 byte accel struct used in Win32 resources (internal only) */
36 typedef struct
37 {
38     WORD   fVirt;
39     WORD   key;
40     WORD   cmd;
41     WORD   pad;
42 } PE_ACCEL;
43
44 /* the accelerator user object */
45 struct accelerator
46 {
47     struct user_object obj;
48     unsigned int       count;
49     PE_ACCEL           table[1];
50 };
51
52 /**********************************************************************
53  *                      LoadAcceleratorsW       (USER32.@)
54  */
55 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance, LPCWSTR name)
56 {
57     struct accelerator *accel;
58     const PE_ACCEL *table;
59     HRSRC rsrc;
60     HACCEL handle;
61     DWORD count;
62
63     if (!(rsrc = FindResourceW( instance, name, (LPWSTR)RT_ACCELERATOR ))) return 0;
64     table = LoadResource( instance, rsrc );
65     count = SizeofResource( instance, rsrc ) / sizeof(*table);
66     if (!count) return 0;
67     accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
68     if (!accel) return 0;
69     accel->count = count;
70     memcpy( accel->table, table, count * sizeof(*table) );
71     if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
72         HeapFree( GetProcessHeap(), 0, accel );
73     TRACE_(accel)("%p %s returning %p\n", instance, debugstr_w(name), handle );
74     return handle;
75 }
76
77 /***********************************************************************
78  *              LoadAcceleratorsA   (USER32.@)
79  */
80 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
81 {
82     INT len;
83     LPWSTR uni;
84     HACCEL result = 0;
85
86     if (IS_INTRESOURCE(lpTableName)) return LoadAcceleratorsW( instance, (LPCWSTR)lpTableName );
87
88     len = MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, NULL, 0 );
89     if ((uni = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
90     {
91         MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, uni, len );
92         result = LoadAcceleratorsW(instance,uni);
93         HeapFree( GetProcessHeap(), 0, uni);
94     }
95     return result;
96 }
97
98 /**********************************************************************
99  *             CopyAcceleratorTableA   (USER32.@)
100  */
101 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT count)
102 {
103     char ch;
104     int i, ret = CopyAcceleratorTableW( src, dst, count );
105
106     if (ret && dst)
107     {
108         for (i = 0; i < ret; i++)
109         {
110             if (dst[i].fVirt & FVIRTKEY) continue;
111             WideCharToMultiByte( CP_ACP, 0, &dst[i].key, 1, &ch, 1, NULL, NULL );
112             dst[i].key = ch;
113         }
114     }
115     return ret;
116 }
117
118 /**********************************************************************
119  *             CopyAcceleratorTableW   (USER32.@)
120  */
121 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT count)
122 {
123     struct accelerator *accel;
124     int i;
125
126     if (!(accel = get_user_handle_ptr( src, USER_ACCEL ))) return 0;
127     if (accel == OBJ_OTHER_PROCESS)
128     {
129         FIXME( "other process handle %p?\n", src );
130         return 0;
131     }
132     if (dst)
133     {
134         if (count > accel->count) count = accel->count;
135         for (i = 0; i < count; i++)
136         {
137             dst[i].fVirt = accel->table[i].fVirt & 0x7f;
138             dst[i].key   = accel->table[i].key;
139             dst[i].cmd   = accel->table[i].cmd;
140         }
141     }
142     else count = accel->count;
143     release_user_handle_ptr( accel );
144     return count;
145 }
146
147 /*********************************************************************
148  *                    CreateAcceleratorTableA   (USER32.@)
149  */
150 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT count)
151 {
152     struct accelerator *accel;
153     HACCEL handle;
154     int i;
155
156     if (count < 1)
157     {
158         SetLastError( ERROR_INVALID_PARAMETER );
159         return 0;
160     }
161     accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
162     if (!accel) return 0;
163     accel->count = count;
164     for (i = 0; i < count; i++)
165     {
166         accel->table[i].fVirt = lpaccel[i].fVirt;
167         accel->table[i].cmd   = lpaccel[i].cmd;
168         if (!(lpaccel[i].fVirt & FVIRTKEY))
169         {
170             char ch = lpaccel[i].key;
171             MultiByteToWideChar( CP_ACP, 0, &ch, 1, &accel->table[i].key, 1 );
172         }
173         else accel->table[i].key = lpaccel[i].key;
174     }
175     if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
176         HeapFree( GetProcessHeap(), 0, accel );
177     TRACE_(accel)("returning %p\n", handle );
178     return handle;
179 }
180
181 /*********************************************************************
182  *                    CreateAcceleratorTableW   (USER32.@)
183  */
184 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT count)
185 {
186     struct accelerator *accel;
187     HACCEL handle;
188     int i;
189
190     if (count < 1)
191     {
192         SetLastError( ERROR_INVALID_PARAMETER );
193         return 0;
194     }
195     accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
196     if (!accel) return 0;
197     accel->count = count;
198     for (i = 0; i < count; i++)
199     {
200         accel->table[i].fVirt = lpaccel[i].fVirt;
201         accel->table[i].key   = lpaccel[i].key;
202         accel->table[i].cmd   = lpaccel[i].cmd;
203     }
204     if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
205         HeapFree( GetProcessHeap(), 0, accel );
206     TRACE_(accel)("returning %p\n", handle );
207     return handle;
208 }
209
210 /******************************************************************************
211  * DestroyAcceleratorTable [USER32.@]
212  * Destroys an accelerator table
213  *
214  * PARAMS
215  *    handle [I] Handle to accelerator table
216  *
217  * RETURNS
218  *    Success: TRUE
219  *    Failure: FALSE
220  */
221 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
222 {
223     struct accelerator *accel;
224
225     if (!(accel = free_user_handle( handle, USER_ACCEL ))) return FALSE;
226     if (accel == OBJ_OTHER_PROCESS)
227     {
228         FIXME( "other process handle %p?\n", accel );
229         return FALSE;
230     }
231     return HeapFree( GetProcessHeap(), 0, accel );
232 }
233
234 /**********************************************************************
235  *      LoadStringW             (USER32.@)
236  */
237 INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
238                             LPWSTR buffer, INT buflen )
239 {
240     HGLOBAL hmem;
241     HRSRC hrsrc;
242     WCHAR *p;
243     int string_num;
244     int i;
245
246     TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
247           instance, resource_id, buffer, buflen);
248
249     if(buffer == NULL)
250         return 0;
251
252     /* Use loword (incremented by 1) as resourceid */
253     hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
254                            (LPWSTR)RT_STRING );
255     if (!hrsrc) return 0;
256     hmem = LoadResource( instance, hrsrc );
257     if (!hmem) return 0;
258
259     p = LockResource(hmem);
260     string_num = resource_id & 0x000f;
261     for (i = 0; i < string_num; i++)
262         p += *p + 1;
263
264     TRACE("strlen = %d\n", (int)*p );
265
266     /*if buflen == 0, then return a read-only pointer to the resource itself in buffer
267     it is assumed that buffer is actually a (LPWSTR *) */
268     if(buflen == 0)
269     {
270         *((LPWSTR *)buffer) = p + 1;
271         return *p;
272     }
273
274     i = min(buflen - 1, *p);
275     if (i > 0) {
276         memcpy(buffer, p + 1, i * sizeof (WCHAR));
277         buffer[i] = 0;
278     } else {
279         if (buflen > 1) {
280             buffer[0] = 0;
281             return 0;
282         }
283     }
284
285     TRACE("%s loaded !\n", debugstr_w(buffer));
286     return i;
287 }
288
289 /**********************************************************************
290  *      LoadStringA     (USER32.@)
291  */
292 INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen )
293 {
294     HGLOBAL hmem;
295     HRSRC hrsrc;
296     DWORD retval = 0;
297
298     TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
299           instance, resource_id, buffer, buflen);
300
301     if (!buflen) return -1;
302
303     /* Use loword (incremented by 1) as resourceid */
304     if ((hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
305                                 (LPWSTR)RT_STRING )) &&
306         (hmem = LoadResource( instance, hrsrc )))
307     {
308         const WCHAR *p = LockResource(hmem);
309         unsigned int id = resource_id & 0x000f;
310
311         while (id--) p += *p + 1;
312
313         RtlUnicodeToMultiByteN( buffer, buflen - 1, &retval, p + 1, *p * sizeof(WCHAR) );
314     }
315     buffer[retval] = 0;
316     TRACE("returning %s\n", debugstr_a(buffer));
317     return retval;
318 }
319
320 /**********************************************************************
321  *      GetGuiResources (USER32.@)
322  */
323 DWORD WINAPI GetGuiResources( HANDLE hProcess, DWORD uiFlags )
324 {
325     static BOOL warn = TRUE;
326
327     if (warn) {
328         FIXME("(%p,%x): stub\n",hProcess,uiFlags);
329        warn = FALSE;
330     }
331
332     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
333     return 0;
334 }