用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

775 lines
24 KiB

5 months ago
/*
* Cursor and icon support
*
* Copyright 1995 Alexandre Julliard
* 1996 Martin Von Loewis
* 1997 Alex Korobka
* 1998 Turchanov Sergey
* 2007 Henri Verbeet
*
* 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
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <windows.h>
#define WARN printf
#pragma warning(disable:4018)
#pragma pack(push,1)
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;
typedef struct
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
} ICONRESDIR;
typedef struct
{
WORD wWidth;
WORD wHeight;
} CURSORDIR;
typedef struct
{ union
{ ICONRESDIR icon;
CURSORDIR cursor;
} ResInfo;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
WORD wResId;
} CURSORICONDIRENTRY;
typedef struct
{
WORD idReserved;
WORD idType;
WORD idCount;
CURSORICONDIRENTRY idEntries[1];
} CURSORICONDIR;
#pragma pack(pop)
static HDC screen_dc;
static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0};
/***********************************************************************
* map_fileW
*
* Helper function to map a file to memory:
* name - file name
* [RETURN] ptr - pointer to mapped file
* [RETURN] filesize - pointer size of file to be stored if not NULL
*/
static const void *map_fileW( LPCWSTR name, LPDWORD filesize )
{
HANDLE hFile, hMapping;
LPVOID ptr = NULL;
hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
if (hFile != INVALID_HANDLE_VALUE)
{
hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if (hMapping)
{
ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle( hMapping );
if (filesize)
*filesize = GetFileSize( hFile, NULL );
}
CloseHandle( hFile );
}
return ptr;
}
/***********************************************************************
* get_dib_image_size
*
* Return the size of a DIB bitmap in bytes.
*/
static int get_dib_image_size( int width, int height, int depth )
{
return (((width * depth + 31) / 8) & ~3) * abs( height );
}
/***********************************************************************
* bitmap_info_size
*
* Return the size of the bitmap info structure including color table.
*/
static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
{
unsigned int colors, size, masks = 0;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
return sizeof(BITMAPCOREHEADER) + colors *
((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
}
else /* assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
if (colors > 256) /* buffer overflow otherwise */
colors = 256;
if (!colors && (info->bmiHeader.biBitCount <= 8))
colors = 1 << info->bmiHeader.biBitCount;
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
size = (std::max)((int) info->bmiHeader.biSize, (int)(sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ));
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
}
}
/***********************************************************************
* is_dib_monochrome
*
* Returns whether a DIB can be converted to a monochrome DDB.
*
* A DIB can be converted if its color table contains only black and
* white. Black must be the first color in the color table.
*
* Note : If the first color in the color table is white followed by
* black, we can't convert it to a monochrome DDB with
* SetDIBits, because black and white would be inverted.
*/
static BOOL is_dib_monochrome( const BITMAPINFO* info )
{
if (info->bmiHeader.biBitCount != 1) return FALSE;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const RGBTRIPLE *rgb = ((const BITMAPCOREINFO*)info)->bmciColors;
/* Check if the first color is black */
if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
{
rgb++;
/* Check if the second color is white */
return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
&& (rgb->rgbtBlue == 0xff));
}
else return FALSE;
}
else /* assume BITMAPINFOHEADER */
{
const RGBQUAD *rgb = info->bmiColors;
/* Check if the first color is black */
if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
(rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
{
rgb++;
/* Check if the second color is white */
return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
&& (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
}
else return FALSE;
}
}
/***********************************************************************
* DIB_GetBitmapInfo
*
* Get the info from a bitmap header.
* Return 1 for INFOHEADER, 0 for COREHEADER, -1 in case of failure.
*/
static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
LONG *height, WORD *bpp, DWORD *compr )
{
if (header->biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
*width = core->bcWidth;
*height = core->bcHeight;
*bpp = core->bcBitCount;
*compr = 0;
return 0;
}
else if (header->biSize == sizeof(BITMAPINFOHEADER) ||
header->biSize == sizeof(BITMAPV4HEADER) ||
header->biSize == sizeof(BITMAPV5HEADER))
{
*width = header->biWidth;
*height = header->biHeight;
*bpp = header->biBitCount;
*compr = header->biCompression;
return 1;
}
return -1;
}
/*
* The following macro functions account for the irregularities of
* accessing cursor and icon resources in files and resource entries.
*/
typedef BOOL (*fnGetCIEntry)( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits );
/**********************************************************************
* CURSORICON_FindBestIcon
*
* Find the icon closest to the requested size and bit depth.
*/
static int CURSORICON_FindBestIcon( LPCVOID dir, DWORD size, fnGetCIEntry get_entry,
int width, int height, int depth, UINT loadflags )
{
int i, cx, cy, bits, bestEntry = -1;
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
/* Find Best Fit */
iTotalDiff = 0xFFFFFFFF;
iColorDiff = 0xFFFFFFFF;
if (loadflags & LR_DEFAULTSIZE)
{
if (!width) width = GetSystemMetrics( SM_CXICON );
if (!height) height = GetSystemMetrics( SM_CYICON );
}
else if (!width && !height)
{
/* use the size of the first entry */
if (!get_entry( dir, size, 0, &width, &height, &bits )) return -1;
iTotalDiff = 0;
}
for ( i = 0; iTotalDiff && get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{
iTempXDiff = abs(width - cx);
iTempYDiff = abs(height - cy);
if(iTotalDiff > (iTempXDiff + iTempYDiff))
{
iXDiff = iTempXDiff;
iYDiff = iTempYDiff;
iTotalDiff = iXDiff + iYDiff;
}
}
/* Find Best Colors for Best Fit */
for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{
if(abs(width - cx) == (int)iXDiff && abs(height - cy) == (int)iYDiff)
{
iTempColorDiff = abs(depth - bits);
if(iColorDiff > iTempColorDiff)
{
bestEntry = i;
iColorDiff = iTempColorDiff;
}
}
}
return bestEntry;
}
static BOOL CURSORICON_GetResIconEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits )
{
const CURSORICONDIR *resdir = (const CURSORICONDIR *)dir;
const ICONRESDIR *icon;
if ( resdir->idCount <= n )
return FALSE;
if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
icon = &resdir->idEntries[n].ResInfo.icon;
*width = icon->bWidth;
*height = icon->bHeight;
*bits = resdir->idEntries[n].wBitCount;
return TRUE;
}
/**********************************************************************
* CURSORICON_FindBestCursor
*
* Find the cursor closest to the requested size.
*
* FIXME: parameter 'color' ignored.
*/
static int CURSORICON_FindBestCursor( LPCVOID dir, DWORD size, fnGetCIEntry get_entry,
int width, int height, int depth, UINT loadflags )
{
int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
if (loadflags & LR_DEFAULTSIZE)
{
if (!width) width = GetSystemMetrics( SM_CXCURSOR );
if (!height) height = GetSystemMetrics( SM_CYCURSOR );
}
else if (!width && !height)
{
/* use the first entry */
if (!get_entry( dir, size, 0, &width, &height, &bits )) return -1;
return 0;
}
/* 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, size, i, &cx, &cy, &bits ); i++ )
{
if ((cx <= width) && (cy <= height) &&
(cx > maxwidth) && (cy > maxheight))
{
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, size, i, &cx, &cy, &bits ); i++ )
{
if (((cx < maxwidth) && (cy < maxheight)) || (bestEntry == -1))
{
bestEntry = i;
maxwidth = cx;
maxheight = cy;
}
}
return bestEntry;
}
static BOOL CURSORICON_GetResCursorEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits )
{
const CURSORICONDIR *resdir = (const CURSORICONDIR *)dir;
const CURSORDIR *cursor;
if ( resdir->idCount <= n )
return FALSE;
if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
cursor = &resdir->idEntries[n].ResInfo.cursor;
*width = cursor->wWidth;
*height = cursor->wHeight;
*bits = resdir->idEntries[n].wBitCount;
return TRUE;
}
static const CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( const CURSORICONDIR * dir, DWORD size,
int width, int height, int depth,
UINT loadflags )
{
int n;
n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetResIconEntry,
width, height, depth, loadflags );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
static const CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( const CURSORICONDIR *dir, DWORD size,
int width, int height, int depth,
UINT loadflags )
{
int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetResCursorEntry,
width, height, depth, loadflags );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
static BOOL CURSORICON_GetFileEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits )
{
const CURSORICONFILEDIR *filedir = (const CURSORICONFILEDIR *)dir;
const CURSORICONFILEDIRENTRY *entry;
const BITMAPINFOHEADER *info;
if ( filedir->idCount <= n )
return FALSE;
if ((const char *)&filedir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
entry = &filedir->idEntries[n];
info = (const BITMAPINFOHEADER *)((const char *)dir + entry->dwDIBOffset);
if ((const char *)(info + 1) - (const char *)dir > size) return FALSE;
*width = entry->bWidth;
*height = entry->bHeight;
*bits = info->biBitCount;
return TRUE;
}
static const CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( const CURSORICONFILEDIR *dir, DWORD size,
int width, int height, int depth,
UINT loadflags )
{
int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetFileEntry,
width, height, depth, loadflags );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
static const CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( const CURSORICONFILEDIR *dir, DWORD size,
int width, int height, int depth,
UINT loadflags )
{
int n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetFileEntry,
width, height, depth, loadflags );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
/***********************************************************************
* bmi_has_alpha
*/
static BOOL bmi_has_alpha( const BITMAPINFO *info, const void *bits )
{
int i;
BOOL has_alpha = FALSE;
const unsigned char *ptr = (const unsigned char *)bits;
if (info->bmiHeader.biBitCount != 32) return FALSE;
for (i = 0; i < info->bmiHeader.biWidth * abs(info->bmiHeader.biHeight); i++, ptr += 4)
{
has_alpha = (ptr[3] != 0);
if ((has_alpha)) break;
}
return has_alpha;
}
/***********************************************************************
* create_alpha_bitmap
*
* Create the alpha bitmap for a 32-bpp icon that has an alpha channel.
*/
static HBITMAP create_alpha_bitmap(const BITMAPINFO *src_info, const void *color_bits,int bmWidth,int bmHeight )
{
HBITMAP alpha = 0;
BITMAPINFO *info = NULL;
HDC hdc;
void *bits;
unsigned char *ptr;
int i;
hdc = CreateCompatibleDC(0);
if (!(hdc)) return 0;
info = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(BITMAPINFO, bmiColors[256]));
if (!(info)) goto done;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info->bmiHeader.biWidth = bmWidth;
info->bmiHeader.biHeight = -bmHeight;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = 32;
info->bmiHeader.biCompression = BI_RGB;
info->bmiHeader.biSizeImage = bmWidth * bmHeight * 4;
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
alpha = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &bits, NULL, 0);
if (!(alpha)) goto done;
SelectObject( hdc, alpha );
StretchDIBits( hdc, 0, 0,bmWidth, bmHeight,
0, 0, src_info->bmiHeader.biWidth, src_info->bmiHeader.biHeight,
color_bits, src_info, DIB_RGB_COLORS, SRCCOPY );
/* pre-multiply by alpha */
for (i = 0, ptr = (unsigned char *)bits; i <bmWidth * bmHeight; i++, ptr += 4)
{
unsigned int alpha = ptr[3];
ptr[0] = ptr[0] * alpha / 255;
ptr[1] = ptr[1] * alpha / 255;
ptr[2] = ptr[2] * alpha / 255;
}
done:
DeleteDC( hdc );
HeapFree( GetProcessHeap(), 0, info );
return alpha;
}
/***********************************************************************
* create_icon_from_bmi
*
* Create an icon from its BITMAPINFO.
*/
static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname,
HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height,
UINT cFlag )
{
DWORD size, color_size, mask_size;
HBITMAP color = 0, mask = 0, alpha = 0;
const void *color_bits, *mask_bits;
BITMAPINFO *bmi_copy;
BOOL ret = FALSE;
BOOL do_stretch;
HICON hObj = 0;
HDC hdc = 0;
/* Check bitmap header */
if (maxsize < sizeof(BITMAPCOREHEADER))
{
return 0;
}
if (maxsize < bmi->bmiHeader.biSize)
{
WARN( "invalid header size %u\n", bmi->bmiHeader.biSize );
return 0;
}
if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
(bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
(bmi->bmiHeader.biCompression != BI_RGB &&
bmi->bmiHeader.biCompression != BI_BITFIELDS)) )
{
WARN( "invalid bitmap header %u\n", bmi->bmiHeader.biSize );
return 0;
}
size = bitmap_info_size( bmi, DIB_RGB_COLORS );
color_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2,
bmi->bmiHeader.biBitCount );
mask_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, 1 );
if (size > maxsize || color_size > maxsize - size)
{
WARN( "truncated file %u < %u+%u+%u\n", maxsize, size, color_size, mask_size );
return 0;
}
if (mask_size > maxsize - size - color_size) mask_size = 0; /* no mask */
if (cFlag & LR_DEFAULTSIZE)
{
if (!width) width = GetSystemMetrics( bIcon ? SM_CXICON : SM_CXCURSOR );
if (!height) height = GetSystemMetrics( bIcon ? SM_CYICON : SM_CYCURSOR );
}
else
{
if (!width) width = bmi->bmiHeader.biWidth;
if (!height) height = bmi->bmiHeader.biHeight/2;
}
do_stretch = (bmi->bmiHeader.biHeight/2 != height) ||
(bmi->bmiHeader.biWidth != width);
/* Scale the hotspot */
if (bIcon)
{
hotspot.x = width / 2;
hotspot.y = height / 2;
}
else if (do_stretch)
{
hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth;
hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biHeight / 2);
}
if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
if (!screen_dc) return 0;
bmi_copy = (BITMAPINFO*)HeapAlloc(GetProcessHeap(), 0, (std::max)((int)size, (int)FIELD_OFFSET(BITMAPINFO, bmiColors[2])));
if (!(bmi_copy))
return 0;
hdc = CreateCompatibleDC(0);
if (!(hdc)) goto done;
memcpy( bmi_copy, bmi, size );
bmi_copy->bmiHeader.biHeight /= 2;
color_bits = (const char*)bmi + size;
mask_bits = (const char*)color_bits + color_size;
alpha = 0;
if (is_dib_monochrome( bmi ))
{
mask = CreateBitmap(width, height * 2, 1, 1, NULL);
if (!(mask)) goto done;
color = 0;
/* copy color data into second half of mask bitmap */
SelectObject( hdc, mask );
StretchDIBits( hdc, 0, height, width, height,
0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight,
color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY );
}
else
{
mask = CreateBitmap(width, height, 1, 1, NULL);
if (!(mask)) goto done;
color = CreateBitmap(width, height, GetDeviceCaps(screen_dc, PLANES),
GetDeviceCaps(screen_dc, BITSPIXEL), NULL);
if (!(color))
{
DeleteObject( mask );
goto done;
}
SelectObject( hdc, color );
StretchDIBits( hdc, 0, 0, width, height,
0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight,
color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY );
if (bmi_has_alpha( bmi_copy, color_bits ))
alpha = create_alpha_bitmap(bmi_copy, color_bits ,width,height);
/* convert info to monochrome to copy the mask */
bmi_copy->bmiHeader.biBitCount = 1;
if (bmi_copy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
{
RGBQUAD *rgb = bmi_copy->bmiColors;
bmi_copy->bmiHeader.biClrUsed = bmi_copy->bmiHeader.biClrImportant = 2;
rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
}
else
{
RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)bmi_copy) + 1);
rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
}
}
if (mask_size)
{
SelectObject( hdc, mask );
StretchDIBits( hdc, 0, 0, width, height,
0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight,
mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY );
}
ret = TRUE;
done:
DeleteDC( hdc );
HeapFree( GetProcessHeap(), 0, bmi_copy );
if(ret)
{
ICONINFO iconInfo={0};
iconInfo.fIcon=bIcon;
iconInfo.xHotspot=hotspot.x;
iconInfo.yHotspot=hotspot.y;
if(alpha)
{
iconInfo.hbmColor=alpha;
iconInfo.hbmMask=mask;
}
else
{
iconInfo.hbmColor=color;
iconInfo.hbmMask=mask;
}
hObj=CreateIconIndirect(&iconInfo);
if(color) DeleteObject( color );
if(alpha) DeleteObject( alpha );
if(mask) DeleteObject( mask );
}
return hObj;
}
HICON CURSORICON_LoadFromBuf(const BYTE * bits,DWORD filesize,INT width, INT height,BOOL fCursor, UINT loadflags)
{
const CURSORICONFILEDIRENTRY *entry;
const CURSORICONFILEDIR *dir;
POINT hotspot;
INT depth=1;
/* Check for .ani. */
if (memcmp( bits, "RIFF", 4 ) == 0)
{//not support
return (HCURSOR)CreateIconFromResource((PBYTE)bits,filesize,FALSE,0x00030000);
}
dir = (const CURSORICONFILEDIR*) bits;
if ( filesize < FIELD_OFFSET( CURSORICONFILEDIR, idEntries[dir->idCount] ))
return 0;
if(!(loadflags & LR_MONOCHROME))
{
HDC hdc=GetDC(NULL);
depth=GetDeviceCaps(hdc,BITSPIXEL);
ReleaseDC(NULL,hdc);
}
if ( fCursor )
entry = CURSORICON_FindBestCursorFile( dir, filesize, width, height, depth, loadflags );
else
entry = CURSORICON_FindBestIconFile( dir, filesize, width, height, depth, loadflags );
/* check that we don't run off the end of the file */
if ( !entry || entry->dwDIBOffset > filesize || entry->dwDIBOffset + entry->dwDIBSize > filesize )
return 0;
hotspot.x = entry->xHotspot;
hotspot.y = entry->yHotspot;
return create_icon_from_bmi( (const BITMAPINFO *)&bits[entry->dwDIBOffset], filesize - entry->dwDIBOffset,
NULL, NULL, NULL, hotspot, !fCursor, width, height, loadflags );
}
HICON CURSORICON_LoadFromFile( LPCWSTR filename,
INT width, INT height,
BOOL fCursor, UINT loadflags)
{
HICON hIcon=0;
DWORD filesize = 0;
const BYTE *bits;
bits = (const BYTE *)map_fileW( filename, &filesize );
if (!bits)
return 0;
hIcon=CURSORICON_LoadFromBuf(bits,filesize,width,height,fCursor,loadflags);
UnmapViewOfFile( bits );
return hIcon;
}