#include <windows.h>

int CALLBACK EXPORT EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable 
   , METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE) 
   { 
   LPBITMAPINFO        lpBI; 
   LPBITMAPINFOHEADER  lpBH; 
   LPBYTE              lpbSrc; 
   LPBYTE              lpbDst; 
   UINT                uWidth, uHeight; 
   DWORD               cb; 
   HGLOBAL             hMem; 
   BITMAP              bm; 
   HBITMAP             hBmp; 
   int                 cxIcon, cyIcon; 
 
 
   //Continue enumeration if we don't see the records we want. 
   if (META_DIBBITBLT!=pMFR->rdFunction && META_DIBSTRETCHBLT!=pMFR->rdFunction) 
      return 1; 
 
   /* 
    * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses 
    * META_DIBSTRETCHBLT so we have to handle each case separately. 
    */ 
 
   if (META_DIBBITBLT==pMFR->rdFunction)       //Win3.0 
      { 
      //Get dimensions and the BITMAPINFO struct. 
      uHeight=pMFR->rdParm[1]; 
      uWidth =pMFR->rdParm[2]; 
      lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]); 
      } 
 
   if (META_DIBSTRETCHBLT==pMFR->rdFunction)   //Win3.1 
      { 
      //Get dimensions and the BITMAPINFO struct. 
      uHeight=pMFR->rdParm[2]; 
      uWidth =pMFR->rdParm[3]; 
      lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]); 
      } 
 
   lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader); 
 
   //Pointer to the bits which follows the BITMAPINFO structure. 
   lpbSrc=(LPBYTE)lpBI+lpBH->biSize; 
 
   //Add the length of the color table. 
   if (0!=lpBH->biClrUsed) 
      lpbSrc+=(DWORD)(lpBH->biClrUsed*sizeof(RGBQUAD)); 
   else 
      { 
      /* 
       * 1 << bc gives 2, 16, 256 for 1, 4, or 8 bits.  24-bit 
       * bitmaps have no color table, so there's no need to 
       * change lpbSrc. 
       */ 
      if (lpBH->biBitCount <= 8) 
          lpbSrc+=(DWORD)((1 << (lpBH->biBitCount))*sizeof(RGBQUAD)); 
      } 
 
 
   /* 
    * All the bits we have in lpbSrc are device-independent, so we 
    * need to change them over to be device-dependent using SetDIBits. 
    * Once we have a bitmap with the device-dependent bits, we can 
    * GetBitmapBits to have buffers with the real data. 
    * 
    * For each pass we have to allocate memory for the bits.  We save 
    * the memory for the mask between passes. 
    */ 
 
   //Use CreateBitmap for ANY monochrome bitmaps 
   if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8) 
      hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL); 
   else if (lpBH->biBitCount <= 8) 
      hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight); 
 
   if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS)) 
      { 
      if (!pIE->fAND) 
         GlobalFree(pIE->hMemAND); 
 
      DeleteObject(hBmp); 
      return 0; 
      } 
 
   //Allocate memory and get the DDBits into it. 
   GetObject(hBmp, sizeof(bm), &bm); 
 
   cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes; 
 
//    if (cb % 4 != 0)        // dword align 
//      cb += 4 - (cb % 4); 
 
   hMem=GlobalAlloc(GHND, cb); 
 
   if (NULL==hMem) 
      { 
      if (NULL!=pIE->hMemAND) 
         GlobalFree(pIE->hMemAND); 
 
      DeleteObject(hBmp); 
      return 0; 
      } 
 
   lpbDst=(LPBYTE)GlobalLock(hMem); 
   GetBitmapBits(hBmp, cb, (LPVOID)lpbDst); 
 
   DeleteObject(hBmp); 
   GlobalUnlock(hMem); 
 
 
   /* 
    * If this is the first pass (pIE->fAND==TRUE) then save the memory 
    * of the AND bits for the next pass. 
    */ 
   if (pIE->fAND) 
      { 
      pIE->fAND=FALSE; 
      pIE->hMemAND=hMem; 
 
      //Continue enumeration looking for the next blt record. 
      return 1; 
      } 
   else 
      { 
      //Get the AND pointer again. 
      lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND); 
 
      /* 
       * Create the icon now that we have all the data.  lpbDst already 
       * points to the XOR bits. 
       */ 
      cxIcon = GetSystemMetrics(SM_CXICON); 
      cyIcon = GetSystemMetrics(SM_CYICON); 
 
      pIE->hIcon=CreateIcon(ghInst, 
                       uWidth, 
                       uHeight, 
                       (BYTE)bm.bmPlanes, 
                       (BYTE)bm.bmBitsPixel, 
                       (LPVOID)lpbSrc, 
                       (LPVOID)lpbDst); 
 
      GlobalUnlock(pIE->hMemAND); 
      GlobalFree(pIE->hMemAND); 
      GlobalFree(hMem); 
 
      //We're done so we can stop. 
      return 0; 
      } 
   } 
 
int CALLBACK EXPORT EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable 
   , METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE) 
   { 
   LPBITMAPINFO        lpBI; 
   LPBITMAPINFOHEADER  lpBH; 
   LPBYTE              lpbSrc; 
   LPBYTE              lpbDst; 
   UINT                uWidth, uHeight; 
   DWORD               cb; 
   HGLOBAL             hMem; 
   BITMAP              bm; 
   HBITMAP             hBmp; 
   int                 cxIcon, cyIcon; 
 
 

   /* 
    * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses 
    * META_DIBSTRETCHBLT so we have to handle each case separately. 
    */ 
 
   if (META_DIBBITBLT==pMFR->rdFunction)       //Win3.0 
      { 
      //Get dimensions and the BITMAPINFO struct. 
      uHeight=pMFR->rdParm[1]; 
      uWidth =pMFR->rdParm[2]; 
      lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]); 
      } 
 
   if (META_DIBSTRETCHBLT==pMFR->rdFunction)   //Win3.1 
      { 
      //Get dimensions and the BITMAPINFO struct. 
      uHeight=pMFR->rdParm[2]; 
      uWidth =pMFR->rdParm[3]; 
      lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]); 
      } 
 
   lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader); 
 
   //Pointer to the bits which follows the BITMAPINFO structure. 
   lpbSrc=(LPBYTE)lpBI+lpBH->biSize; 
 
   //Add the length of the color table. 
   if (0!=lpBH->biClrUsed) 
      lpbSrc+=(DWORD)(lpBH->biClrUsed*sizeof(RGBQUAD)); 
   else 
      { 
      /* 
       * 1 << bc gives 2, 16, 256 for 1, 4, or 8 bits.  24-bit 
       * bitmaps have no color table, so there's no need to 
       * change lpbSrc. 
       */ 
      if (lpBH->biBitCount <= 8) 
          lpbSrc+=(DWORD)((1 << (lpBH->biBitCount))*sizeof(RGBQUAD)); 
      } 
 
 
   /* 
    * All the bits we have in lpbSrc are device-independent, so we 
    * need to change them over to be device-dependent using SetDIBits. 
    * Once we have a bitmap with the device-dependent bits, we can 
    * GetBitmapBits to have buffers with the real data. 
    * 
    * For each pass we have to allocate memory for the bits.  We save 
    * the memory for the mask between passes. 
    */ 
 
   //Use CreateBitmap for ANY monochrome bitmaps 
   if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8) 
      hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL); 
   else if (lpBH->biBitCount <= 8) 
      hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight); 
 
   if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS)) 
      { 
      if (!pIE->fAND) 
         GlobalFree(pIE->hMemAND); 
 
      DeleteObject(hBmp); 
      return 0; 
      } 
 
   //Allocate memory and get the DDBits into it. 
   GetObject(hBmp, sizeof(bm), &bm); 
 
   cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes; 
 
//    if (cb % 4 != 0)        // dword align 
//      cb += 4 - (cb % 4); 
 
   hMem=GlobalAlloc(GHND, cb); 
 
   if (NULL==hMem) 
      { 
      if (NULL!=pIE->hMemAND) 
         GlobalFree(pIE->hMemAND); 
 
      DeleteObject(hBmp); 
      return 0; 
      } 
 
   lpbDst=(LPBYTE)GlobalLock(hMem); 
   GetBitmapBits(hBmp, cb, (LPVOID)lpbDst); 
 
   DeleteObject(hBmp); 
   GlobalUnlock(hMem); 
 
 
   /* 
    * If this is the first pass (pIE->fAND==TRUE) then save the memory 
    * of the AND bits for the next pass. 
    */ 
   if (pIE->fAND) 
      { 
      pIE->fAND=FALSE; 
      pIE->hMemAND=hMem; 
 
      //Continue enumeration looking for the next blt record. 
      return 1; 
      } 
   else 
      { 
      //Get the AND pointer again. 
      lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND); 
 
      /* 
       * Create the icon now that we have all the data.  lpbDst already 
       * points to the XOR bits. 
       */ 
      cxIcon = GetSystemMetrics(SM_CXICON); 
      cyIcon = GetSystemMetrics(SM_CYICON); 
 
      pIE->hIcon=CreateIcon(ghInst, 
                       uWidth, 
                       uHeight, 
                       (BYTE)bm.bmPlanes, 
                       (BYTE)bm.bmBitsPixel, 
                       (LPVOID)lpbSrc, 
                       (LPVOID)lpbDst); 
 
      GlobalUnlock(pIE->hMemAND); 
      GlobalFree(pIE->hMemAND); 
      GlobalFree(hMem); 
 
      //We're done so we can stop. 
      return 0; 
      } 
   } 
 
 