update for HEAD-2003091401
[reactos.git] / lib / user32 / windows / bitmap.c
index ef95d34..3609601 100644 (file)
 #include <windows.h>
 #include <user32.h>
 #include <debug.h>
+#include <stdlib.h>
+
+/*forward declerations... actualy in user32\windows\icon.c but usful here****/
+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,
@@ -63,6 +73,339 @@ LoadImageA(HINSTANCE hinst,
   return(Handle);
 }
 
+
+HANDLE STATIC
+LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)
+{
+  HANDLE hResource;
+  HANDLE h2Resource;
+  HANDLE hFile;
+  HANDLE hSection;
+  CURSORICONDIR* IconDIR;
+  HDC hScreenDc;
+  HANDLE hIcon;
+  ULONG HeaderSize;
+  ULONG ColourCount;
+  PVOID Data;
+  CURSORICONDIRENTRY* dirEntry;
+  ICONIMAGE* SafeIconImage;
+  GRPCURSORICONDIR* IconResDir;
+  INT id;
+  ICONIMAGE *ResIcon;
+
+  if (fuLoad & LR_SHARED)
+    DbgPrint("FIXME: need LR_SHARED support Loading cursor images\n");
+
+  if (!(fuLoad & LR_LOADFROMFILE))
+  {
+      if (hinst == NULL)
+         {
+           hinst = GetModuleHandleW(L"USER32");
+         }
+      hResource = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      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);
+         }
+      return CreateIconFromResourceEx((PBYTE) ResIcon,
+                  SizeofResource(hinst, h2Resource), FALSE, 0x00030000,
+                  32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+  }
+  else
+  {
+      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);
+         }
+
+      //pick the best size.
+      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, 32, 32, 1);
+
+
+      if (!dirEntry)
+         {
+         if (fuLoad & LR_LOADFROMFILE)
+                {
+              UnmapViewOfFile(IconDIR);
+                }
+         return(NULL);
+         }
+
+      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+
+      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+  }
+
+  //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;
+      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+    }
+  else
+    {
+      ColourCount = SafeIconImage->icHeader.biClrUsed;
+      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+       {
+         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+       }
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * 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(RtlGetProcessHeap(), 0, SafeIconImage);
+        UnmapViewOfFile(IconDIR);
+         }
+      return(NULL);
+  }
+
+  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
+  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  return hIcon;
+}
+
+
+HANDLE STATIC
+LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
+{
+  HANDLE hResource;
+  HANDLE h2Resource;
+  HANDLE hFile;
+  HANDLE hSection;
+  CURSORICONDIR* IconDIR;
+  HDC hScreenDc;
+  HANDLE hIcon;
+  ULONG HeaderSize;
+  ULONG ColourCount;
+  PVOID Data;
+  CURSORICONDIRENTRY* dirEntry;
+  ICONIMAGE* SafeIconImage;
+  GRPCURSORICONDIR* IconResDir;
+  INT id;
+  ICONIMAGE *ResIcon;
+
+  if (fuLoad & LR_SHARED)
+    DbgPrint("FIXME: need LR_SHARED support Loading icon images\n");
+
+  if (!(fuLoad & LR_LOADFROMFILE))
+  {
+      if (hinst == NULL)
+         {
+           hinst = GetModuleHandleW(L"USER32");
+         }
+      hResource = FindResourceW(hinst, lpszName, RT_GROUP_ICON);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      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);
+         }
+      return CreateIconFromResourceEx((PBYTE) ResIcon,
+                  SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
+                  width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+  }
+  else
+  {
+      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);
+         }
+
+      //pick the best size.
+      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, width, height, 1);
+
+
+      if (!dirEntry)
+         {
+         if (fuLoad & LR_LOADFROMFILE)
+                {
+              UnmapViewOfFile(IconDIR);
+                }
+         return(NULL);
+         }
+
+      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+
+      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+  }
+
+  //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;
+      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+    }
+  else
+    {
+      ColourCount = SafeIconImage->icHeader.biClrUsed;
+      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+       {
+         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+       }
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * 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(RtlGetProcessHeap(), 0, SafeIconImage);
+        UnmapViewOfFile(IconDIR);
+         }
+      return(NULL);
+  }
+
+  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
+  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  return hIcon;
+}
+
+
 HANDLE STATIC
 LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
 {
@@ -81,7 +424,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
     {
       if (hInstance == NULL)
        {
-         hInstance = GetModuleHandle(L"USER32");               
+         hInstance = GetModuleHandleW(L"USER32");
        }
       hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
       if (hResource == NULL)
@@ -101,7 +444,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
     }
   else
     {
-      hFile = CreateFile(lpszName,
+      hFile = CreateFileW(lpszName,
                         GENERIC_READ,
                         FILE_SHARE_READ,
                         NULL,
@@ -112,7 +455,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
        {
          return(NULL);
        }
-      hSection = CreateFileMapping(hFile,
+      hSection = CreateFileMappingW(hFile,
                                   NULL,
                                   PAGE_READONLY,
                                   0,
@@ -123,9 +466,9 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
        {               
          return(NULL);
        }
-      BitmapInfo = MapViewOfFile(hSection, 
+      BitmapInfo = MapViewOfFile(hSection,
                                 FILE_MAP_READ,
-                                0, 
+                                0,
                                 0,
                                 0);
       CloseHandle(hSection);
@@ -133,6 +476,10 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
        {
          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))
@@ -242,8 +589,11 @@ LoadImageW(HINSTANCE hinst,
       }
     case IMAGE_CURSOR:
       {
-       DbgPrint("FIXME: Need support for loading cursor images.\n");
-       return(NULL);
+       return(LoadCursorImage(hinst, lpszName, fuLoad));
+      }
+    case IMAGE_ICON:
+      {
+       return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));
       }
     default:
       DbgBreakPoint();
@@ -253,12 +603,19 @@ LoadImageW(HINSTANCE hinst,
 }
 
 
+/*
+ * @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)
 {