Check for failed allocations and fix some resource leaks.
[reactos.git] / reactos / lib / user32 / windows / bitmap.c
index b38d1eb..16b03fb 100644 (file)
@@ -16,7 +16,7 @@
  *  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.22 2003/12/09 19:43:38 gvg Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS user32.dll
  * FILE:            lib/user32/windows/input.c
 
 /* INCLUDES ******************************************************************/
 
-#include <string.h>
-#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_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
@@ -40,7 +36,6 @@ HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, in
 CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
 CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
 
-
 /* FUNCTIONS *****************************************************************/
 
 /*
@@ -59,7 +54,7 @@ LoadImageA(HINSTANCE hinst,
   UNICODE_STRING NameString;
 
   if (HIWORD(lpszName))
-    {      
+    {
       RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
       lpszWName = NameString.Buffer;
       Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
@@ -75,189 +70,198 @@ LoadImageA(HINSTANCE hinst,
 }
 
 
-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 ColourCount;
-  PVOID Data;
-  CURSORICONDIRENTRY* dirEntry;
-  ICONIMAGE* SafeIconImage;
-  GRPCURSORICONDIR* IconResDir;
-  INT id;
-  ICONIMAGE *ResIcon;
-  
-  if (!(fuLoad & LR_LOADFROMFILE))
-  {
+   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");
-         }
+      {
+         hinst = GetModuleHandleW(L"USER32");
+      }
       hResource = hfRes = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);
       if (hResource == NULL)
-         {
-           return(NULL);
-         }
-         
-         if (fuLoad & LR_SHARED)
       {
-        hIcon = (HANDLE)NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes);
-        if(hIcon)
-          return hIcon;
+         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);
-         }
+      {
+         return NULL;
+      }
       IconResDir = LockResource(hResource);
       if (IconResDir == NULL)
-         {
-           return(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));
+      /* 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));
+      h2Resource = FindResourceW(hinst, MAKEINTRESOURCEW(id),
+         MAKEINTRESOURCEW(RT_CURSOR));
 
       hResource = LoadResource(hinst, h2Resource);
       if (hResource == NULL)
-         {
-           return(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)
       {
-        NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, 
-                                (HRSRC)NULL);
+         return NULL;
       }
-      return hIcon;
-  }
-  else
-  {
-      if (fuLoad & LR_SHARED)
+
+      hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE)ResIcon,
+         SizeofResource(hinst, h2Resource), FALSE, 0x00030000,
+         32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+      if (hIcon && 0 != (fuLoad & LR_SHARED))
       {
-        DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
+         NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,
+                                 (HRSRC)NULL);
       }
-      
-      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);
+      return hIcon;
+   }
 
-      CloseHandle(hFile);
-      if (hSection == NULL)
-         {
-           return(NULL);
-         }
-      IconDIR = MapViewOfFile(hSection,
-                                FILE_MAP_READ,
-                                0,
-                                0,
-                                0);
+   if (fuLoad & LR_SHARED)
+   {
+      DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
+   }
 
-      CloseHandle(hSection);
-      if (IconDIR == NULL)
-         {
-           return(NULL);
-         }
+   hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
+      OPEN_EXISTING, 0, NULL);
+   if (hFile == NULL)
+   {
+      return NULL;
+   }
 
-      //pick the best size.
-      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, 32, 32, 1);
+   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 (!dirEntry)
-         {
-         if (fuLoad & LR_LOADFROMFILE)
-                {
-              UnmapViewOfFile(IconDIR);
-                }
-         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;
+   }
 
-      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+   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;
+   }
 
-      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
-  }
+   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
+   /* at this point we have a copy of the icon image to play with */
 
-  SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+   SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
 
-  if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
-    {
+   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)
+      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)
        {
-         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+         ColorCount = 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;
+      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(RtlGetProcessHeap(), 0, SafeIconImage);
-        UnmapViewOfFile(IconDIR);
-         }
-      return(NULL);
-  }
-
-  hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
-  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
-  return hIcon;
+   hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
+   DeleteDC(hScreenDc);
+   RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+   return hIcon;
 }
 
 
-HANDLE STATIC
+static HANDLE
 LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
 {
   HANDLE hResource;
@@ -269,14 +273,14 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
   HDC hScreenDc;
   HANDLE hIcon;
   ULONG HeaderSize;
-  ULONG ColourCount;
+  ULONG ColorCount;
   PVOID Data;
   CURSORICONDIRENTRY* dirEntry;
   ICONIMAGE* SafeIconImage;
   GRPCURSORICONDIR* IconResDir;
   INT id;
   ICONIMAGE *ResIcon;
-  
+
   if (!(fuLoad & LR_LOADFROMFILE))
   {
       if (hinst == NULL)
@@ -288,17 +292,13 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
          {
            return(NULL);
          }
-         
-#if 0
-      /* Code temporarily deactivated until NtUserFindExistingCursorIcon
-         can take requested width/height into account */
+
       if (fuLoad & LR_SHARED)
           {
-            hIcon = NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes);
+            hIcon = NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes, width, height);
             if(hIcon)
               return hIcon;
           }
-#endif
 
       hResource = LoadResource(hinst, hResource);
       if (hResource == NULL)
@@ -333,20 +333,28 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
       hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE) ResIcon,
                         SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
                         width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
-      if(hIcon)
+      if (hIcon && 0 != (fuLoad & LR_SHARED))
       {
-        NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, 
+        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,
@@ -355,9 +363,9 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
                         0,
                         NULL);
       if (hFile == NULL)
-         {
-           return(NULL);
-         }
+      {
+          return NULL;
+      }
 
       hSection = CreateFileMappingW(hFile,
                                   NULL,
@@ -366,42 +374,42 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
                                   0,
                                   NULL);
 
+      CloseHandle(hFile);
       if (hSection == NULL)
-         {
-           CloseHandle(hFile);
-           return(NULL);
-         }
+      {
+          return NULL;
+      }
+
       IconDIR = MapViewOfFile(hSection,
                                 FILE_MAP_READ,
                                 0,
                                 0,
                                 0);
-
+      CloseHandle(hSection);
       if (IconDIR == NULL)
-         {
-           CloseHandle(hFile);
-           CloseHandle(hSection);
-           return(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)
-         {
-              CloseHandle(hFile);
-              CloseHandle(hSection);
-              UnmapViewOfFile(IconDIR);
-              return(NULL);
-         }
+      {
+          UnmapViewOfFile(IconDIR);
+          return NULL;
+      }
 
-      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+      SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
 
       memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
-
-      CloseHandle(hFile);
-      CloseHandle(hSection);
+      UnmapViewOfFile(IconDIR);
   }
 
   //at this point we have a copy of the icon image to play with
@@ -411,19 +419,19 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
   if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
     {
       BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
-      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 = SafeIconImage->icHeader.biClrUsed;
-      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+      ColorCount = SafeIconImage->icHeader.biClrUsed;
+      if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
        {
-         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+         ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
        }
-      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
     }
-  
+
   //make data point to the start of the XOR image data
   Data = (PBYTE)SafeIconImage + HeaderSize;
 
@@ -433,20 +441,19 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL
   if (hScreenDc == NULL)
   {
       if (fuLoad & LR_LOADFROMFILE)
-         {
-               RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
-        UnmapViewOfFile(IconDIR);
-         }
+      {
+         RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+      }
       return(NULL);
   }
 
   hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
-  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
   return hIcon;
 }
 
 
-HANDLE STATIC
+static HANDLE
 LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
 {
   HANDLE hResource;
@@ -457,7 +464,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
   HDC hScreenDc;
   HANDLE hBitmap;
   ULONG HeaderSize;
-  ULONG ColourCount;
+  ULONG ColorCount;
   PVOID Data;
 
   if (!(fuLoad & LR_LOADFROMFILE))
@@ -503,7 +510,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
                                   NULL);
       CloseHandle(hFile);
       if (hSection == NULL)
-       {               
+       {
          return(NULL);
        }
       BitmapInfo = MapViewOfFile(hSection,
@@ -525,21 +532,21 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
   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)
@@ -550,11 +557,12 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
     }
   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);
@@ -566,7 +574,7 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
     {
       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,
@@ -578,8 +586,8 @@ LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
                               Data, PrivateInfo, DIB_RGB_COLORS);
     }
 
-  RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo);
-  /*DeleteDC(hScreenDc);*/
+  RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
+  DeleteDC(hScreenDc);
   if (fuLoad & LR_LOADFROMFILE)
     {
       UnmapViewOfFile(BitmapInfo);
@@ -594,7 +602,7 @@ LoadImageW(HINSTANCE hinst,
           int cxDesired,
           int cyDesired,
           UINT fuLoad)
-{  
+{
   if (fuLoad & LR_DEFAULTSIZE)
     {
       if (uType == IMAGE_ICON)
@@ -664,35 +672,59 @@ LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
 
 
 /*
- * @implemented
+ * @unimplemented
  */
 HANDLE WINAPI
 CopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
 {
-   switch (type)
-   {
-      case IMAGE_BITMAP:
-         {
-            HBITMAP res;
-            BITMAP bm;
-
-            if (!GetObjectW(hnd, sizeof(bm), &bm)) return 0;
-            bm.bmBits = NULL;
-            if ((res = CreateBitmapIndirect(&bm)))
-            {
-               char *buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight);
-               GetBitmapBits(hnd, bm.bmWidthBytes * bm.bmHeight, buf);
-               SetBitmapBits(res, bm.bmWidthBytes * bm.bmHeight, buf);
-               HeapFree(GetProcessHeap(), 0, buf);
-            }
-            return (HICON)res;
-        }
-     case IMAGE_ICON:
-        DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
-        return CopyIcon(hnd);
-     case IMAGE_CURSOR:
-        DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
-        return CopyCursor(hnd);
-    }
-    return 0;
+    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;
 }