mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:25:41 +00:00
fixed LoadCursorIconImage (Thunderbird is now working)
svn path=/trunk/; revision=20849
This commit is contained in:
parent
a5da271b47
commit
6fca38c9bf
1 changed files with 124 additions and 13 deletions
|
@ -30,6 +30,29 @@
|
||||||
|
|
||||||
#include <user32.h>
|
#include <user32.h>
|
||||||
|
|
||||||
|
#include "pshpack1.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BYTE bWidth;
|
||||||
|
BYTE bHeight;
|
||||||
|
BYTE bColorCount;
|
||||||
|
BYTE bReserved;
|
||||||
|
WORD xHotspot;
|
||||||
|
WORD yHotspot;
|
||||||
|
DWORD dwDIBSize;
|
||||||
|
DWORD dwDIBOffset;
|
||||||
|
} CURSORICONFILEDIRENTRY;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORD idReserved;
|
||||||
|
WORD idType;
|
||||||
|
WORD idCount;
|
||||||
|
CURSORICONFILEDIRENTRY idEntries[1];
|
||||||
|
} CURSORICONFILEDIR;
|
||||||
|
|
||||||
|
#include "poppack.h"
|
||||||
|
|
||||||
/*forward declerations... actualy in user32\windows\icon.c but usful here****/
|
/*forward declerations... actualy in user32\windows\icon.c but usful here****/
|
||||||
HICON ICON_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
|
HICON ICON_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
|
||||||
HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
|
HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
|
||||||
|
@ -71,6 +94,87 @@ LoadImageA(HINSTANCE hinst,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following macro functions account for the irregularities of
|
||||||
|
* accessing cursor and icon resources in files and resource entries.
|
||||||
|
*/
|
||||||
|
typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n,
|
||||||
|
int *width, int *height, int *bits );
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* CURSORICON_FindBestCursor2
|
||||||
|
*
|
||||||
|
* Find the cursor closest to the requested size.
|
||||||
|
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
|
||||||
|
* ignored too
|
||||||
|
*/
|
||||||
|
static int CURSORICON_FindBestCursor2( LPVOID dir, fnGetCIEntry get_entry,
|
||||||
|
int width, int height, int color )
|
||||||
|
{
|
||||||
|
int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
|
||||||
|
|
||||||
|
/* Double height to account for AND and XOR masks */
|
||||||
|
|
||||||
|
height *= 2;
|
||||||
|
|
||||||
|
/* First find the largest one smaller than or equal to the requested size*/
|
||||||
|
|
||||||
|
maxwidth = maxheight = 0;
|
||||||
|
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
|
||||||
|
{
|
||||||
|
if ((cx <= width) && (cy <= height) &&
|
||||||
|
(cx > maxwidth) && (cy > maxheight) &&
|
||||||
|
(bits == 1))
|
||||||
|
{
|
||||||
|
bestEntry = i;
|
||||||
|
maxwidth = cx;
|
||||||
|
maxheight = cy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestEntry != -1) return bestEntry;
|
||||||
|
|
||||||
|
/* Now find the smallest one larger than the requested size */
|
||||||
|
|
||||||
|
maxwidth = maxheight = 255;
|
||||||
|
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
|
||||||
|
{
|
||||||
|
if (((cx < maxwidth) && (cy < maxheight) && (bits == 1)) ||
|
||||||
|
(bestEntry==-1))
|
||||||
|
{
|
||||||
|
bestEntry = i;
|
||||||
|
maxwidth = cx;
|
||||||
|
maxheight = cy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n,
|
||||||
|
int *width, int *height, int *bits )
|
||||||
|
{
|
||||||
|
CURSORICONFILEDIR *filedir = dir;
|
||||||
|
CURSORICONFILEDIRENTRY *entry;
|
||||||
|
|
||||||
|
if ( filedir->idCount <= n )
|
||||||
|
return FALSE;
|
||||||
|
entry = &filedir->idEntries[n];
|
||||||
|
*width = entry->bWidth;
|
||||||
|
*height = entry->bHeight;
|
||||||
|
*bits = entry->bColorCount;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir,
|
||||||
|
int width, int height, int color )
|
||||||
|
{
|
||||||
|
int n = CURSORICON_FindBestCursor2( dir, CURSORICON_GetFileEntry,
|
||||||
|
width, height, color );
|
||||||
|
if ( n < 0 )
|
||||||
|
return NULL;
|
||||||
|
return &dir->idEntries[n];
|
||||||
|
}
|
||||||
|
|
||||||
static HANDLE
|
static HANDLE
|
||||||
LoadCursorIconImage(
|
LoadCursorIconImage(
|
||||||
HINSTANCE hinst,
|
HINSTANCE hinst,
|
||||||
|
@ -85,19 +189,20 @@ LoadCursorIconImage(
|
||||||
HANDLE hfRes;
|
HANDLE hfRes;
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
HANDLE hSection;
|
HANDLE hSection;
|
||||||
CURSORICONDIR *IconDIR;
|
CURSORICONFILEDIR *IconDIR;
|
||||||
HDC hScreenDc;
|
HDC hScreenDc;
|
||||||
HICON hIcon;
|
HICON hIcon;
|
||||||
ULONG HeaderSize;
|
ULONG HeaderSize;
|
||||||
ULONG ColorCount;
|
ULONG ColorCount;
|
||||||
ULONG ColorBits;
|
ULONG ColorBits;
|
||||||
PVOID Data;
|
PVOID Data;
|
||||||
CURSORICONDIRENTRY* dirEntry;
|
CURSORICONFILEDIRENTRY* dirEntry;
|
||||||
ICONIMAGE* SafeIconImage = NULL;
|
ICONIMAGE* SafeIconImage = NULL;
|
||||||
GRPCURSORICONDIR* IconResDir;
|
GRPCURSORICONDIR* IconResDir;
|
||||||
INT id;
|
INT id;
|
||||||
ICONIMAGE *ResIcon;
|
ICONIMAGE *ResIcon;
|
||||||
BOOL Icon = (uType == IMAGE_ICON);
|
BOOL Icon = (uType == IMAGE_ICON);
|
||||||
|
DWORD filesize = 0;
|
||||||
|
|
||||||
if (!(fuLoad & LR_LOADFROMFILE))
|
if (!(fuLoad & LR_LOADFROMFILE))
|
||||||
{
|
{
|
||||||
|
@ -158,14 +263,6 @@ LoadCursorIconImage(
|
||||||
return hIcon;
|
return hIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: This code is incorrect and is likely to crash in many cases.
|
|
||||||
* In the file the cursor/icon directory records are stored like
|
|
||||||
* CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
|
|
||||||
* this is solved by creating a fake cursor/icon directory in memory
|
|
||||||
* and passing that to CURSORICON_FindBestIcon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (fuLoad & LR_SHARED)
|
if (fuLoad & LR_SHARED)
|
||||||
{
|
{
|
||||||
DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
|
DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
|
||||||
|
@ -177,6 +274,7 @@ LoadCursorIconImage(
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
|
filesize = GetFileSize( hFile, NULL );
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
if (hSection == NULL)
|
if (hSection == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -219,7 +317,7 @@ LoadCursorIconImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pick the best size. */
|
/* Pick the best size. */
|
||||||
dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, width, height, ColorBits);
|
dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits );
|
||||||
if (!dirEntry)
|
if (!dirEntry)
|
||||||
{
|
{
|
||||||
DeleteDC(hScreenDc);
|
DeleteDC(hScreenDc);
|
||||||
|
@ -227,7 +325,20 @@ LoadCursorIconImage(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
|
if ( dirEntry->dwDIBOffset > filesize )
|
||||||
|
{
|
||||||
|
DeleteDC(hScreenDc);
|
||||||
|
UnmapViewOfFile(IconDIR);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dirEntry->dwDIBOffset + dirEntry->dwDIBSize > filesize ){
|
||||||
|
DeleteDC(hScreenDc);
|
||||||
|
UnmapViewOfFile(IconDIR);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize);
|
||||||
if (SafeIconImage == NULL)
|
if (SafeIconImage == NULL)
|
||||||
{
|
{
|
||||||
DeleteDC(hScreenDc);
|
DeleteDC(hScreenDc);
|
||||||
|
@ -235,7 +346,7 @@ LoadCursorIconImage(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
|
memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwDIBOffset, dirEntry->dwDIBSize);
|
||||||
UnmapViewOfFile(IconDIR);
|
UnmapViewOfFile(IconDIR);
|
||||||
|
|
||||||
/* At this point we have a copy of the icon image to play with. */
|
/* At this point we have a copy of the icon image to play with. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue