user32: Return empty string from LoadStringW() if resource is not found.
[wine.git] / dlls / user32 / resource.c
blobd29379887654e887fe54df8edc550483a5359f4e
1 /*
2 * USER resource functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995, 2009 Alexandre Julliard
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.
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.
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
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "ntuser.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(resource);
31 WINE_DECLARE_DEBUG_CHANNEL(accel);
33 /* this is the 8 byte accel struct used in Win32 resources (internal only) */
34 typedef struct
36 WORD fVirt;
37 WORD key;
38 WORD cmd;
39 WORD pad;
40 } PE_ACCEL;
42 /**********************************************************************
43 * LoadAcceleratorsW (USER32.@)
45 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance, LPCWSTR name)
47 const PE_ACCEL *pe_table;
48 ACCEL *table;
49 unsigned int i;
50 HRSRC rsrc;
51 HACCEL handle;
52 DWORD count;
54 if (!(rsrc = FindResourceW( instance, name, (LPWSTR)RT_ACCELERATOR ))) return 0;
55 pe_table = LoadResource( instance, rsrc );
56 count = SizeofResource( instance, rsrc ) / sizeof(*pe_table);
57 if (!count) return 0;
58 table = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*table) );
59 if (!table) return 0;
60 for (i = 0; i < count; i++)
62 table[i].fVirt = pe_table[i].fVirt;
63 table[i].key = pe_table[i].key;
64 table[i].cmd = pe_table[i].cmd;
66 handle = NtUserCreateAcceleratorTable( table, count );
67 HeapFree( GetProcessHeap(), 0, table );
68 TRACE_(accel)("%p %s returning %p\n", instance, debugstr_w(name), handle );
69 return handle;
72 /***********************************************************************
73 * LoadAcceleratorsA (USER32.@)
75 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
77 INT len;
78 LPWSTR uni;
79 HACCEL result = 0;
81 if (IS_INTRESOURCE(lpTableName)) return LoadAcceleratorsW( instance, (LPCWSTR)lpTableName );
83 len = MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, NULL, 0 );
84 if ((uni = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
86 MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, uni, len );
87 result = LoadAcceleratorsW(instance,uni);
88 HeapFree( GetProcessHeap(), 0, uni);
90 return result;
93 /**********************************************************************
94 * CopyAcceleratorTableA (USER32.@)
96 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT count)
98 char ch;
99 int i, ret = NtUserCopyAcceleratorTable( src, dst, count );
101 if (ret && dst)
103 for (i = 0; i < ret; i++)
105 if (dst[i].fVirt & FVIRTKEY) continue;
106 WideCharToMultiByte( CP_ACP, 0, &dst[i].key, 1, &ch, 1, NULL, NULL );
107 dst[i].key = ch;
110 return ret;
113 /*********************************************************************
114 * CreateAcceleratorTableA (USER32.@)
116 HACCEL WINAPI CreateAcceleratorTableA( ACCEL *accel, INT count )
118 HACCEL handle;
119 ACCEL *table;
120 int i;
122 if (count < 1)
124 SetLastError( ERROR_INVALID_PARAMETER );
125 return 0;
127 table = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*table) );
128 if (!table) return 0;
129 for (i = 0; i < count; i++)
131 table[i].fVirt = accel[i].fVirt;
132 table[i].cmd = accel[i].cmd;
133 if (!(accel[i].fVirt & FVIRTKEY))
135 char ch = accel[i].key;
136 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &table[i].key, 1 );
138 else table[i].key = accel[i].key;
140 handle = NtUserCreateAcceleratorTable( table, count );
141 HeapFree( GetProcessHeap(), 0, table );
142 TRACE_(accel)("returning %p\n", handle );
143 return handle;
146 /**********************************************************************
147 * LoadStringW (USER32.@)
149 INT WINAPI DECLSPEC_HOTPATCH LoadStringW( HINSTANCE instance, UINT resource_id,
150 LPWSTR buffer, INT buflen )
152 HGLOBAL hmem;
153 HRSRC hrsrc;
154 WCHAR *p;
155 int string_num;
156 int i;
158 TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
159 instance, resource_id, buffer, buflen);
161 if(buffer == NULL)
162 return 0;
164 if (!(hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1), (LPWSTR)RT_STRING )) ||
165 !(hmem = LoadResource( instance, hrsrc )))
167 TRACE( "Failed to load string.\n" );
168 if (buflen > 0) buffer[0] = 0;
169 return 0;
172 p = LockResource(hmem);
173 string_num = resource_id & 0x000f;
174 for (i = 0; i < string_num; i++)
175 p += *p + 1;
177 TRACE("strlen = %d\n", (int)*p );
179 /*if buflen == 0, then return a read-only pointer to the resource itself in buffer
180 it is assumed that buffer is actually a (LPWSTR *) */
181 if(buflen == 0)
183 *((LPWSTR *)buffer) = p + 1;
184 return *p;
187 i = min(buflen - 1, *p);
188 if (i > 0) {
189 memcpy(buffer, p + 1, i * sizeof (WCHAR));
190 buffer[i] = 0;
191 } else {
192 if (buflen > 1) {
193 buffer[0] = 0;
194 return 0;
198 TRACE("%s loaded !\n", debugstr_w(buffer));
199 return i;
202 /**********************************************************************
203 * LoadStringA (USER32.@)
205 INT WINAPI DECLSPEC_HOTPATCH LoadStringA( HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen )
207 HGLOBAL hmem;
208 HRSRC hrsrc;
209 DWORD retval = 0;
211 TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
212 instance, resource_id, buffer, buflen);
214 if (!buflen) return -1;
216 /* Use loword (incremented by 1) as resourceid */
217 if ((hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
218 (LPWSTR)RT_STRING )) &&
219 (hmem = LoadResource( instance, hrsrc )))
221 const WCHAR *p = LockResource(hmem);
222 unsigned int id = resource_id & 0x000f;
224 while (id--) p += *p + 1;
226 RtlUnicodeToMultiByteN( buffer, buflen - 1, &retval, p + 1, *p * sizeof(WCHAR) );
228 buffer[retval] = 0;
229 TRACE("returning %s\n", debugstr_a(buffer));
230 return retval;
233 /**********************************************************************
234 * GetGuiResources (USER32.@)
236 DWORD WINAPI GetGuiResources( HANDLE hProcess, DWORD uiFlags )
238 static BOOL warn = TRUE;
240 if (warn) {
241 FIXME("(%p,%lx): stub\n",hProcess,uiFlags);
242 warn = FALSE;
245 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
246 return 0;