* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: bitmap.c,v 1.2 2002/09/03 22:44:20 dwelch Exp $
+/* $Id$
*
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c
/* INCLUDES ******************************************************************/
-#include <windows.h>
#include <user32.h>
-#include <debug.h>
+
+/*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_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
+CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
+CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
/* FUNCTIONS *****************************************************************/
+/*
+ * @implemented
+ */
HANDLE STDCALL
LoadImageA(HINSTANCE hinst,
LPCSTR lpszName,
{
LPWSTR lpszWName;
HANDLE Handle;
+ UNICODE_STRING NameString;
if (HIWORD(lpszName))
{
- lpszWName = User32ConvertString(lpszName);
+ RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
+ lpszWName = NameString.Buffer;
Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
cyDesired, fuLoad);
- User32FreeString(lpszWName);
+ RtlFreeUnicodeString(&NameString);
}
else
{
- Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
+ Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
cyDesired, fuLoad);
}
return(Handle);
}
-HANDLE STATIC
+
+static HANDLE
+LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)
+{
+ HANDLE hResource;
+ HANDLE h2Resource;
+ HANDLE hfRes;
+ HANDLE hFile;
+ HANDLE hSection;
+ CURSORICONDIR *IconDIR;
+ HDC hScreenDc;
+ HANDLE hIcon;
+ ULONG HeaderSize;
+ ULONG ColorCount;
+ PVOID Data;
+ CURSORICONDIRENTRY* dirEntry;
+ ICONIMAGE* SafeIconImage;
+ GRPCURSORICONDIR* IconResDir;
+ INT id;
+ ICONIMAGE *ResIcon;
+ UINT ColorBits;
+
+ if (!(fuLoad & LR_LOADFROMFILE))
+ {
+ if (hinst == NULL)
+ {
+ hinst = GetModuleHandleW(L"USER32");
+ }
+ hResource = hfRes = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);
+ if (hResource == NULL)
+ {
+ return NULL;
+ }
+
+ if (fuLoad & LR_SHARED)
+ {
+ /* FIXME - pass size! */
+ hIcon = (HANDLE)NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes, 0, 0);
+ if (hIcon)
+ {
+ return hIcon;
+ }
+ }
+
+ hResource = LoadResource(hinst, hResource);
+ if (hResource == NULL)
+ {
+ return NULL;
+ }
+ IconResDir = LockResource(hResource);
+ if (IconResDir == NULL)
+ {
+ return NULL;
+ }
+
+ /* Find the best fitting in the IconResDir for this resolution. */
+ id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, TRUE,
+ 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+
+ h2Resource = FindResourceW(hinst, MAKEINTRESOURCEW(id),
+ MAKEINTRESOURCEW(RT_CURSOR));
+
+ hResource = LoadResource(hinst, h2Resource);
+ if (hResource == NULL)
+ {
+ return NULL;
+ }
+
+ ResIcon = LockResource(hResource);
+ if (ResIcon == NULL)
+ {
+ return NULL;
+ }
+
+ hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE)ResIcon,
+ SizeofResource(hinst, h2Resource), FALSE, 0x00030000,
+ 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+ if (hIcon && 0 != (fuLoad & LR_SHARED))
+ {
+ NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,
+ (HRSRC)NULL);
+ }
+
+ return hIcon;
+ }
+
+ if (fuLoad & LR_SHARED)
+ {
+ DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
+ }
+
+ hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if (hFile == NULL)
+ {
+ return NULL;
+ }
+
+ hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ CloseHandle(hFile);
+ if (hSection == NULL)
+ {
+ return NULL;
+ }
+
+ IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(hSection);
+ if (IconDIR == NULL)
+ {
+ return NULL;
+ }
+
+ if (0 != IconDIR->idReserved ||
+ (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+
+ /*
+ * Get a handle to the screen dc, the icon we create is going to be
+ * compatable with it.
+ */
+ hScreenDc = CreateCompatibleDC(0);
+ if (hScreenDc == NULL)
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+
+ if (fuLoad & LR_MONOCHROME)
+ {
+ ColorBits = 1;
+ }
+ else
+ {
+ ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL);
+ /*
+ * FIXME:
+ * Remove this after proper support for alpha icons will be finished.
+ */
+ if (ColorBits > 8)
+ ColorBits = 8;
+ }
+
+ /* Pick the best size. */
+ dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits);
+ if (!dirEntry)
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+
+ SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
+ if (SafeIconImage == NULL)
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+ memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+ UnmapViewOfFile(IconDIR);
+
+ /* at this point we have a copy of the icon image to play with */
+
+ SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+
+ if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
+ ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+ HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
+ }
+ else
+ {
+ ColorCount = SafeIconImage->icHeader.biClrUsed;
+ if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+ {
+ ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
+ }
+ HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
+ }
+
+ /* make data point to the start of the XOR image data */
+ Data = (PBYTE)SafeIconImage + HeaderSize;
+
+ hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
+ DeleteDC(hScreenDc);
+ RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+ return hIcon;
+}
+
+
+static HANDLE
+LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
+{
+ HANDLE hResource;
+ HANDLE h2Resource;
+ HANDLE hfRes;
+ HANDLE hFile;
+ HANDLE hSection;
+ CURSORICONDIR* IconDIR;
+ HDC hScreenDc;
+ HANDLE hIcon;
+ ULONG HeaderSize;
+ ULONG ColorCount;
+ PVOID Data;
+ CURSORICONDIRENTRY* dirEntry;
+ ICONIMAGE* SafeIconImage;
+ GRPCURSORICONDIR* IconResDir;
+ INT id;
+ ICONIMAGE *ResIcon;
+
+ if (!(fuLoad & LR_LOADFROMFILE))
+ {
+ if (hinst == NULL)
+ {
+ hinst = GetModuleHandleW(L"USER32");
+ }
+ hResource = hfRes = FindResourceW(hinst, lpszName, RT_GROUP_ICON);
+ if (hResource == NULL)
+ {
+ return(NULL);
+ }
+
+ if (fuLoad & LR_SHARED)
+ {
+ hIcon = NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes, width, height);
+ if(hIcon)
+ return hIcon;
+ }
+
+ hResource = LoadResource(hinst, hResource);
+ if (hResource == NULL)
+ {
+ return(NULL);
+ }
+ IconResDir = LockResource(hResource);
+ if (IconResDir == NULL)
+ {
+ return(NULL);
+ }
+
+ //find the best fitting in the IconResDir for this resolution
+ id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,
+ width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+
+ h2Resource = FindResourceW(hinst,
+ MAKEINTRESOURCEW(id),
+ MAKEINTRESOURCEW(RT_ICON));
+
+ hResource = LoadResource(hinst, h2Resource);
+ if (hResource == NULL)
+ {
+ return(NULL);
+ }
+
+ ResIcon = LockResource(hResource);
+ if (ResIcon == NULL)
+ {
+ return(NULL);
+ }
+ hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE) ResIcon,
+ SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
+ width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+ if (hIcon && 0 != (fuLoad & LR_SHARED))
+ {
+ NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,
+ (HRSRC)NULL);
+ }
+ return hIcon;
+ }
+ else
+ {
+ /*
+ * 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)
+ {
+ DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
+ }
+
+ hFile = CreateFileW(lpszName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (hFile == NULL)
+ {
+ return NULL;
+ }
+
+ hSection = CreateFileMappingW(hFile,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 0,
+ NULL);
+
+ CloseHandle(hFile);
+ if (hSection == NULL)
+ {
+ return NULL;
+ }
+
+ IconDIR = MapViewOfFile(hSection,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ 0);
+ CloseHandle(hSection);
+ if (IconDIR == NULL)
+ {
+ return NULL;
+ }
+
+ if (0 != IconDIR->idReserved ||
+ (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+
+ //pick the best size.
+ dirEntry = (CURSORICONDIRENTRY *) CURSORICON_FindBestIcon( IconDIR, width, height, 1);
+ if (!dirEntry)
+ {
+ UnmapViewOfFile(IconDIR);
+ return NULL;
+ }
+
+ SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
+
+ memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+ UnmapViewOfFile(IconDIR);
+ }
+
+ //at this point we have a copy of the icon image to play with
+
+ SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+
+ if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
+ ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+ HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
+ }
+ else
+ {
+ ColorCount = SafeIconImage->icHeader.biClrUsed;
+ if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+ {
+ ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
+ }
+ HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
+ }
+
+ //make data point to the start of the XOR image data
+ Data = (PBYTE)SafeIconImage + HeaderSize;
+
+
+ //get a handle to the screen dc, the icon we create is going to be compatable with this
+ hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+ if (hScreenDc == NULL)
+ {
+ if (fuLoad & LR_LOADFROMFILE)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+ }
+ return(NULL);
+ }
+
+ hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
+ RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+ return hIcon;
+}
+
+
+static HANDLE
LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
{
HANDLE hResource;
HDC hScreenDc;
HANDLE hBitmap;
ULONG HeaderSize;
- ULONG ColourCount;
+ ULONG ColorCount;
PVOID Data;
if (!(fuLoad & LR_LOADFROMFILE))
{
if (hInstance == NULL)
{
- hInstance = GetModuleHandle(L"USER32");
+ hInstance = GetModuleHandleW(L"USER32");
}
hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
if (hResource == NULL)
}
else
{
- hFile = CreateFile(lpszName,
+ hFile = CreateFileW(lpszName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
{
return(NULL);
}
- hSection = CreateFileMapping(hFile,
+ hSection = CreateFileMappingW(hFile,
NULL,
PAGE_READONLY,
0,
NULL);
CloseHandle(hFile);
if (hSection == NULL)
- {
+ {
return(NULL);
}
- BitmapInfo = MapViewOfFile(hSection,
+ BitmapInfo = MapViewOfFile(hSection,
FILE_MAP_READ,
- 0,
+ 0,
0,
0);
CloseHandle(hSection);
{
return(NULL);
}
+ /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
+ unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
+ */
+ BitmapInfo = (BITMAPINFO*)(((PBYTE)BitmapInfo) + 14);
}
if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
- ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
- HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+ ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+ HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
}
else
{
- ColourCount = BitmapInfo->bmiHeader.biClrUsed;
- if (ColourCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
+ ColorCount = BitmapInfo->bmiHeader.biClrUsed;
+ if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
{
- ColourCount = 1 << BitmapInfo->bmiHeader.biBitCount;
+ ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount;
}
- HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+ HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
}
- Data = (PVOID)BitmapInfo + HeaderSize;
+ Data = (PVOID)((ULONG_PTR)BitmapInfo + HeaderSize);
- PrivateInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, HeaderSize);
+ PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize);
if (PrivateInfo == NULL)
{
if (fuLoad & LR_LOADFROMFILE)
}
memcpy(PrivateInfo, BitmapInfo, HeaderSize);
- /* FIXME: Handle colour conversion and transparency. */
+ /* FIXME: Handle color conversion and transparency. */
- hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+ hScreenDc = CreateCompatibleDC(NULL);
if (hScreenDc == NULL)
{
+ RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
if (fuLoad & LR_LOADFROMFILE)
{
UnmapViewOfFile(BitmapInfo);
{
DIBSECTION Dib;
- hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
+ hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
0, 0);
GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
Data, PrivateInfo, DIB_RGB_COLORS);
}
- RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo);
- /*DeleteDC(hScreenDc);*/
+ RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
+ DeleteDC(hScreenDc);
if (fuLoad & LR_LOADFROMFILE)
{
UnmapViewOfFile(BitmapInfo);
int cxDesired,
int cyDesired,
UINT fuLoad)
-{
+{
if (fuLoad & LR_DEFAULTSIZE)
{
if (uType == IMAGE_ICON)
}
case IMAGE_CURSOR:
{
- DbgPrint("FIXME: Need support for loading cursors.\n");
- return(NULL);
+ return(LoadCursorImage(hinst, lpszName, fuLoad));
+ }
+ case IMAGE_ICON:
+ {
+ return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));
}
default:
DbgBreakPoint();
}
+/*
+ * @implemented
+ */
HBITMAP STDCALL
LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
{
return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
}
+
+/*
+ * @implemented
+ */
HBITMAP STDCALL
LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
{
return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
}
+
+
+/*
+ * @unimplemented
+ */
+HANDLE WINAPI
+CopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
+{
+ HBITMAP res;
+ BITMAP bm;
+
+ switch (type)
+ {
+ case IMAGE_BITMAP:
+ {
+ DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
+ /* FIXME: support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
+ LR_COPYRETURNORG, LR_CREATEDIBSECTION,
+ and LR_MONOCHROME; */
+
+ if (!GetObjectW(hnd, sizeof(bm), &bm)) return 0;
+ bm.bmBits = NULL;
+ if ((res = CreateBitmapIndirect(&bm)))
+ {
+ char *buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight);
+ if (buf == NULL)
+ {
+ DeleteObject(res);
+ return NULL;
+ }
+ GetBitmapBits(hnd, bm.bmWidthBytes * bm.bmHeight, buf);
+ SetBitmapBits(res, bm.bmWidthBytes * bm.bmHeight, buf);
+ HeapFree(GetProcessHeap(), 0, buf);
+ }
+ return res;
+ }
+ case IMAGE_ICON:
+ {
+ static BOOL IconMsgDisplayed = FALSE;
+ /* FIXME: support loading the image as shared from an instance */
+ if (!IconMsgDisplayed) {
+ DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
+ IconMsgDisplayed = TRUE;
+ }
+ return CopyIcon(hnd);
+ }
+ case IMAGE_CURSOR:
+ {
+ static BOOL IconMsgDisplayed = FALSE;
+ /* FIXME: support loading the image as shared from an instance */
+ if (!IconMsgDisplayed) {
+ DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
+ IconMsgDisplayed = TRUE;
+ }
+ return CopyCursor(hnd);
+ }
+ }
+ return 0;
+}