resource.c 12.3 KB
Newer Older
1 2 3 4 5
/*
 * USER resource functions
 *
 * Copyright 1993 Robert J. Amstadt
 * Copyright 1995 Alexandre Julliard
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23
#include <stdarg.h>

24 25 26 27 28 29
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include "wine/winbase16.h"
#include "wine/winuser16.h"
30
#include "wownt32.h"
31
#include "wine/debug.h"
32

33 34
WINE_DEFAULT_DEBUG_CHANNEL(resource);
WINE_DECLARE_DEBUG_CHANNEL(accel);
35

36 37 38
/* this is the 8 byte accel struct used in Win32 resources (internal only) */
typedef struct
{
39
    WORD   fVirt;
40 41
    WORD   key;
    WORD   cmd;
42
    WORD   pad;
43 44
} PE_ACCEL, *LPPE_ACCEL;

45
/**********************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
46
 *			LoadAccelerators	[USER.177]
47
 */
48
HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
49 50 51
{
    HRSRC16	hRsrc;

52
    TRACE_(accel)("%04x %s\n", instance, debugstr_a(lpTableName) );
53

54
    if (!(hRsrc = FindResource16( instance, lpTableName, (LPSTR)RT_ACCELERATOR ))) {
55 56 57 58 59 60 61 62 63
      WARN_(accel)("couldn't find accelerator table resource\n");
      return 0;
    }

    TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
    return LoadResource16(instance,hRsrc);
}

/**********************************************************************
64
 *			LoadAcceleratorsW	(USER32.@)
65
 * The image layout seems to look like this (not 100% sure):
66
 * 00:	WORD	type		type of accelerator
67
 * 02:	WORD	event
68
 * 04:	WORD	IDval
69 70 71 72 73
 * 06:	WORD	pad		(to DWORD boundary)
 */
HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
{
    HRSRC hRsrc;
74 75
    HACCEL hMem;
    HACCEL16 hRetval=0;
76 77 78 79
    DWORD size;

    if (HIWORD(lpTableName))
        TRACE_(accel)("%p '%s'\n",
Eric Pouech's avatar
Eric Pouech committed
80
                      (LPVOID)instance, (const char *)( lpTableName ) );
81 82 83 84
    else
        TRACE_(accel)("%p 0x%04x\n",
                       (LPVOID)instance, LOWORD(lpTableName) );

85
    if (!(hRsrc = FindResourceW( instance, lpTableName, (LPWSTR)RT_ACCELERATOR )))
86 87 88 89 90 91 92 93 94 95 96 97 98 99
    {
      WARN_(accel)("couldn't find accelerator table resource\n");
    } else {
      hMem = LoadResource( instance, hRsrc );
      size = SizeofResource( instance, hRsrc );
      if(size>=sizeof(PE_ACCEL))
      {
	LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
	LPACCEL16 accel16;
	int i,nrofaccells = size/sizeof(PE_ACCEL);

	hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
	accel16 = (LPACCEL16)GlobalLock16(hRetval);
	for (i=0;i<nrofaccells;i++) {
100 101 102 103 104
          accel16[i].fVirt = accel_table[i].fVirt & 0x7f;
          accel16[i].key = accel_table[i].key;
          if( !(accel16[i].fVirt & FVIRTKEY) )
            accel16[i].key &= 0x00ff;
          accel16[i].cmd = accel_table[i].cmd;
105 106 107 108
	}
	accel16[i-1].fVirt |= 0x80;
      }
    }
109
    TRACE_(accel)("returning HACCEL %p\n", hRsrc);
110
    return HACCEL_32(hRetval);
111 112 113
}

/***********************************************************************
114
 *		LoadAcceleratorsA   (USER32.@)
115 116 117
 */
HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
{
118 119 120 121 122 123 124 125 126 127 128 129 130 131
    INT len;
    LPWSTR uni;
    HACCEL result = 0;

    if (!HIWORD(lpTableName)) return LoadAcceleratorsW( instance, (LPCWSTR)lpTableName );

    len = MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, NULL, 0 );
    if ((uni = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
    {
        MultiByteToWideChar( CP_ACP, 0, lpTableName, -1, uni, len );
        result = LoadAcceleratorsW(instance,uni);
        HeapFree( GetProcessHeap(), 0, uni);
    }
    return result;
132 133 134
}

/**********************************************************************
135
 *             CopyAcceleratorTableA   (USER32.@)
136 137 138 139 140 141 142
 */
INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
{
  return CopyAcceleratorTableW(src, dst, entries);
}

/**********************************************************************
143
 *             CopyAcceleratorTableW   (USER32.@)
144 145 146 147 148 149 150
 *
 * By mortene@pvv.org 980321
 */
INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
				     INT entries)
{
  int i,xsize;
151
  LPACCEL16 accel = (LPACCEL16)GlobalLock16(HACCEL_16(src));
152 153 154 155
  BOOL done = FALSE;

  /* Do parameter checking to avoid the explosions and the screaming
     as far as possible. */
156
  if((dst && (entries < 1)) || (src == NULL) || !accel) {
157 158 159 160
    WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
	 (LPVOID)src, (LPVOID)dst, entries);
    return 0;
  }
161
  xsize = GlobalSize16(HACCEL_16(src))/sizeof(ACCEL16);
162
  if (xsize<entries) entries=xsize;
163 164 165 166 167 168 169 170 171 172

  i=0;
  while(!done) {
    /* Spit out some debugging information. */
    TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
	  i, accel[i].fVirt, accel[i].key, accel[i].cmd);

    /* Copy data to the destination structure array (if dst == NULL,
       we're just supposed to count the number of entries). */
    if(dst) {
173
      dst[i].fVirt = accel[i].fVirt&0x7f;
174 175 176 177 178
      dst[i].key = accel[i].key;
      dst[i].cmd = accel[i].cmd;

      /* Check if we've reached the end of the application supplied
         accelerator table. */
179
      if(i+1 == entries)
180 181 182 183 184 185 186 187 188 189 190 191 192 193
	done = TRUE;
    }

    /* The highest order bit seems to mark the end of the accelerator
       resource table, but not always. Use GlobalSize() check too. */
    if((accel[i].fVirt & 0x80) != 0) done = TRUE;

    i++;
  }

  return i;
}

/*********************************************************************
194
 *                    CreateAcceleratorTableA   (USER32.@)
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
 *
 * By mortene@pvv.org 980321
 */
HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
{
  HACCEL	hAccel;
  LPACCEL16	accel;
  int		i;

  /* Do parameter checking just in case someone's trying to be
     funny. */
  if(cEntries < 1) {
    WARN_(accel)("Application sent invalid parameters (%p %d).\n",
	 lpaccel, cEntries);
    SetLastError(ERROR_INVALID_PARAMETER);
210
    return NULL;
211 212 213
  }

  /* Allocate memory and copy the table. */
214
  hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
215

216
  TRACE_(accel)("handle %p\n", hAccel);
217 218 219
  if(!hAccel) {
    ERR_(accel)("Out of memory.\n");
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
220
    return NULL;
221
  }
222
  accel = GlobalLock16(HACCEL_16(hAccel));
223
  for (i=0;i<cEntries;i++) {
224 225 226 227 228
    accel[i].fVirt = lpaccel[i].fVirt&0x7f;
    accel[i].key = lpaccel[i].key;
    if( !(accel[i].fVirt & FVIRTKEY) )
      accel[i].key &= 0x00ff;
    accel[i].cmd = lpaccel[i].cmd;
229 230 231 232
  }
  /* Set the end-of-table terminator. */
  accel[cEntries-1].fVirt |= 0x80;

233
  TRACE_(accel)("Allocated accelerator handle %p with %d entries\n", hAccel,cEntries);
234 235 236 237
  return hAccel;
}

/*********************************************************************
238
 *                    CreateAcceleratorTableW   (USER32.@)
239
 *
240
 *
241 242 243 244 245 246
 */
HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
{
  HACCEL	hAccel;
  LPACCEL16	accel;
  int		i;
247
  char		ckey;
248 249 250 251 252 253 254

  /* Do parameter checking just in case someone's trying to be
     funny. */
  if(cEntries < 1) {
    WARN_(accel)("Application sent invalid parameters (%p %d).\n",
	 lpaccel, cEntries);
    SetLastError(ERROR_INVALID_PARAMETER);
255
    return NULL;
256 257 258
  }

  /* Allocate memory and copy the table. */
259
  hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
260

261
  TRACE_(accel)("handle %p\n", hAccel);
262 263 264
  if(!hAccel) {
    ERR_(accel)("Out of memory.\n");
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
265
    return NULL;
266
  }
267
  accel = GlobalLock16(HACCEL_16(hAccel));
268 269 270


  for (i=0;i<cEntries;i++) {
271
       accel[i].fVirt = lpaccel[i].fVirt&0x7f;
272 273 274
       if( !(accel[i].fVirt & FVIRTKEY) ) {
	  ckey = (char) lpaccel[i].key;
         if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
275
            WARN_(accel)("Error converting ASCII accelerator table to Unicode\n");
276
       }
277 278
       else
         accel[i].key = lpaccel[i].key;
279 280 281 282 283 284
       accel[i].cmd = lpaccel[i].cmd;
  }

  /* Set the end-of-table terminator. */
  accel[cEntries-1].fVirt |= 0x80;

285
  TRACE_(accel)("Allocated accelerator handle %p\n", hAccel);
286 287 288 289
  return hAccel;
}

/******************************************************************************
290
 * DestroyAcceleratorTable [USER32.@]
291 292 293 294 295 296 297 298
 * Destroys an accelerator table
 *
 * NOTES
 *    By mortene@pvv.org 980321
 *
 * PARAMS
 *    handle [I] Handle to accelerator table
 *
299 300 301
 * RETURNS
 *    Success: TRUE
 *    Failure: FALSE
302 303 304
 */
BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
{
305 306
    if( !handle )
        return FALSE;
307
    return !GlobalFree16(HACCEL_16(handle));
308
}
309

310
/**********************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
311
 *     LoadString   (USER.176)
312 313 314 315 316 317 318 319 320 321
 */
INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
                           LPSTR buffer, INT16 buflen )
{
    HGLOBAL16 hmem;
    HRSRC16 hrsrc;
    unsigned char *p;
    int string_num;
    int i;

322 323
    TRACE("inst=%04x id=%04x buff=%p len=%d\n",
          instance, resource_id, buffer, buflen);
324

325
    hrsrc = FindResource16( instance, MAKEINTRESOURCEA((resource_id>>4)+1), (LPSTR)RT_STRING );
326 327 328
    if (!hrsrc) return 0;
    hmem = LoadResource16( instance, hrsrc );
    if (!hmem) return 0;
329

330 331 332 333
    p = LockResource16(hmem);
    string_num = resource_id & 0x000f;
    for (i = 0; i < string_num; i++)
	p += *p + 1;
334

335
    TRACE("strlen = %d\n", (int)*p );
336

337 338 339 340 341 342 343 344 345 346
    if (buffer == NULL) return *p;
    i = min(buflen - 1, *p);
    if (i > 0) {
	memcpy(buffer, p + 1, i);
	buffer[i] = '\0';
    } else {
	if (buflen > 1) {
	    buffer[0] = '\0';
	    return 0;
	}
347
	WARN("Don't know why caller gave buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
348 349 350 351 352 353 354 355
    }
    FreeResource16( hmem );

    TRACE("'%s' loaded !\n", buffer);
    return i;
}

/**********************************************************************
356
 *	LoadStringW		(USER32.@)
357 358 359 360 361 362 363 364 365 366
 */
INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
                            LPWSTR buffer, INT buflen )
{
    HGLOBAL hmem;
    HRSRC hrsrc;
    WCHAR *p;
    int string_num;
    int i;

367 368
    TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
          instance, resource_id, buffer, buflen);
369

370 371
    /* Use loword (incremented by 1) as resourceid */
    hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
372
                           (LPWSTR)RT_STRING );
373 374 375
    if (!hrsrc) return 0;
    hmem = LoadResource( instance, hrsrc );
    if (!hmem) return 0;
376

377 378 379 380
    p = LockResource(hmem);
    string_num = resource_id & 0x000f;
    for (i = 0; i < string_num; i++)
	p += *p + 1;
381

382
    TRACE("strlen = %d\n", (int)*p );
383

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    if (buffer == NULL) return *p;
    i = min(buflen - 1, *p);
    if (i > 0) {
	memcpy(buffer, p + 1, i * sizeof (WCHAR));
	buffer[i] = (WCHAR) 0;
    } else {
	if (buflen > 1) {
	    buffer[0] = (WCHAR) 0;
	    return 0;
	}
    }

    TRACE("%s loaded !\n", debugstr_w(buffer));
    return i;
}

/**********************************************************************
401
 *	LoadStringA	(USER32.@)
402 403 404 405 406 407 408
 */
INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id,
                            LPSTR buffer, INT buflen )
{
    INT    retval;
    LPWSTR wbuf;

409 410
    TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n",
          instance, resource_id, buffer, buflen);
411 412 413

    if(buffer == NULL) /* asked size of string */
	return LoadStringW(instance, resource_id, NULL, 0);
414

415 416 417 418 419 420 421 422 423 424 425
    wbuf = HeapAlloc(GetProcessHeap(), 0, buflen * sizeof(WCHAR));
    if(!wbuf)
	return 0;

    retval = LoadStringW(instance, resource_id, wbuf, buflen);
    if(retval != 0)
    {
	retval = WideCharToMultiByte(CP_ACP, 0, wbuf, retval, buffer, buflen - 1, NULL, NULL);
	buffer[retval] = 0;
	TRACE("%s loaded !\n", debugstr_a(buffer));
    }
426
    else buffer[0] = 0;    /* no check of buflen here */
427 428 429 430
    HeapFree( GetProcessHeap(), 0, wbuf );

    return retval;
}
431 432 433 434 435 436

/**********************************************************************
 *	GetGuiResources	(USER32.@)
 */
DWORD WINAPI GetGuiResources( HANDLE hProcess, DWORD uiFlags )
{
437
    FIXME("(%p,%x): stub\n",hProcess,uiFlags);
438 439 440
    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
    return 0;
}