/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDBGETB                                       */
/*                                                                    */
/*   Description     = Display Device Driver Function :               */
/*                     Get/SetBitmapBits                              */
/*                                                                    */
/*   Function        = GetBitmapBits transfers data from a bitmap to  */
/*                     application storage                            */
/*                     SetBitmapBits transfers data from application  */
/*                     storage to a bitmap                            */
/*                                                                    */
/*                                                                    */
/*   73894 - Jim Reid  Modified GetBitmapBits to handle the occasion  */
/*                     when only the color table is requested         */
/*                     for a 2 color bitmap.  Previously, the         */
/*                     function returned 16 color table values        */
/*                     when only 2 color table values should have     */
/*                     been returned.                                 */
/*                                                                    */
/*   77638 - JOHNB     Added support for 16 bit external bitmaps.     */
/*                     These will only be used when we are using      */
/*                     16 bit internal bitmaps ( we are in 64K        */
/*                     color mode ). For this file the change         */
/*                     consisted of removing blocks of code.          */
/*                                                                    */
/**********************************************************************/

#define INCL_DDICOMFLAGS
#define INCL_DDIMISC
#define INCL_GRE_BITMAPS
#define INCL_DOSSEMAPHORES
#include "eddinclt.h"

#include "eddbtypt.h"

#include "bitmaps.h"
#include "errors.h"

#include "eddbextf.h"
#include "eddgextf.h"

#include "edddtypt.h"                                                 /*73894*/
#include "eddbcone.h"

#include "memman.h"
#include <semaphor.h>

#include <eddncach.h>

extern PPFNL EnginesDispatchTable;
extern ULONG FullSizeDeviceDefaultPalette[];

/**********************************************************************/
/* We need to prototype this specifically because it takes parameters */
/* of varying type - we want the compiler to check types for us.      */
/**********************************************************************/
ULONG APIENTRY InnerGre32Entry9(HDC,ULONG,ULONG,PBITMAPINFO2,PBYTE,
                                PBITMAPINFO2,PBYTE,ULONG,ULONG);

/**********************************************************************/
/*                                                                    */
/*   GetBitmapBits transfers data from from a given bitmap to         */
/* application storage.  It is only valid for a Memory DC. If the     */
/* given bitmap handle is null then the currently selected bitmap in  */
/* the given DC is used (an error is returned if there is no          */
/* currently selected bitmap in the given DC).                        */
/*                                                                    */
/*   The application defines the region of the bitmap to be set in    */
/* terms of a number of scanlines.  Scanline # 0 is taken             */
/* to be the bottom scanline (in the PM sense).                       */
/* Scanlines are numbered upward.  The actual number of scanlines     */
/* for which data is obtained is returned (this may be less than the  */
/* application requested).                                            */
/*                                                                    */
/*   The application gives the device driver two pointers; the        */
/* BitmapBits and a BitmapInfoTable with which to interpret these     */
/* bits.                                                              */
/*                                                                    */
/*   The bitcount and number of planes in the table have been set     */
/* by the application; the device driver returns an error if this     */
/* does not correspond to a standard PM format.                       */
/*                                                                    */
/*   The device driver sets the width and height in this table; it    */
/* also sets a pointer to a colour table.  This new BitmapInfoTable   */
/* then defines the meaning of the bits which the device driver       */
/* places in application storage                                      */
/*                                                                    */
/**********************************************************************/
DDIENTRY GetBitmapBits (HDC          hdc,
                        HBITMAP      hBitmap,
                        LONG         lScanStart,
                        LONG         clScanCount,
                        PBYTE        pArgAddress,
                        PBITMAPINFO2 pArgInfo,
                        PDC          pdcArg,
                        ULONG        FunN)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    pBitmapHeader       pbhBitmap;
    LONG                lScanLinesGot;
    BOOL                fCompression;
    PBITMAPINFO2        pInfo;
    PBYTE               pAddress;
    POINTL              ptlStartPoint;
    ULONG               i;
    PRGB                pRGB;                                         /*73894*/

    EnterDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);
    COMMANDBITS(FunN) &= pdc->DCICommandMask;

#ifdef FIREWALLS
    /******************************************************************/
    /* Check that the function number is GetBitmapBits                */
    /* Changes to the engine headers have previously caused problems. */
    /******************************************************************/
    if ( !FUNCTIONIS(FunN, NGreGetBitmapBits) )
    {
        DebugOutput("Invalid function number for GetBitmapBits!\r\n");
        haltproc();
    }
#endif

    /******************************************************************/
    /* Assume no conversion (compression or decompression) of the     */
    /* new format bitmap is needed.                                   */
    /******************************************************************/
    fCompression = FALSE;

    /******************************************************************/
    /* Get the bitmap header for the bitmap from which the bits are   */
    /* to be retrieved/set in to.                                     */
    /******************************************************************/
    pbhBitmap = GetBMHeader(hBitmap);

    /******************************************************************/
    /* Check parameter validity.                                      */
    /******************************************************************/
    if ( (pbhBitmap == NULL)                        ||
         IllegallyInPath(FunN)                      ||
         InvalidScanCount(clScanCount)              ||
         !ValidHeader(pArgInfo)                     ||
         ScanStartOutsideBM(lScanStart, pbhBitmap) )
    {
        lScanLinesGot = GPI_ALTERROR;
        goto GETBITS_EXIT;
    }

    /******************************************************************/
    /* Defect 61458 - We were not handling the special case when      */
    /* the engine calls this DDI with a NULL pointer for the          */
    /* PBITMAPINFO structure.                                         */
    /*                                                                */
    /* If we do get a NULL pointer we simply copy the logical color   */
    /* table from the DC to the callers data area.                    */
    /******************************************************************/
    if (pArgAddress == NULL) {

       if (pArgInfo->cBitCount == 8) {

          if (pdc->DCIColFormat != LCOLF_PALETTE)
             for ( i = 0; i < 256; i++)
                *(PULONG)&(pArgInfo->argbColor[i]) =
                   (FullSizeDeviceDefaultPalette[i] & 0xffffff);
          else
             for ( i = 0; i < pdc->Palette->usCountStored; i++) {
                pArgInfo->argbColor[i] = pdc->Palette->entries[i].rgb;
                pArgInfo->argbColor[i].fcOptions = 0;
             }
       }

       else if (pArgInfo->cBitCount == 4) {                           /*73894*/
          for ( i = 0; i <= pdc->DCIHighIndex; i++)
             pArgInfo->argbColor[i] = pdc->DCIColorTable[i].LogRGB;
       }
       else {                                                         /*73894*/
                                                                      /*73894*/
          pRGB = (PRGB)((PBYTE)pArgInfo + pArgInfo->cbFix);           /*73894*/
                                                                      /*73894*/
          if (OldFormatBitmap(pArgInfo)) {                            /*73894*/
             SetRGBAndInc(&pRGB, 0x00, 0x00, 0x00);                   /*73894*/
             SetRGBAndInc(&pRGB, 0xFF, 0xFF, 0xFF);                   /*73894*/
          }                                                           /*73894*/
          else {                                                      /*73894*/
             SetRGB2AndInc(&pRGB, 0x00, 0x00, 0x00);                  /*73894*/
             SetRGB2AndInc(&pRGB, 0xFF, 0xFF, 0xFF);                  /*73894*/
          }                                                           /*73894*/
       }                                                              /*73894*/

       lScanLinesGot = 0;
       goto GETBITS_EXIT;

    }

    /******************************************************************/
    /* Set up the number of scanlines to be obtained. This is not     */
    /* necessarily the number requested.                              */
    /* Leave function if Scan lines to be obtained is zero.           */
    /******************************************************************/
    lScanLinesGot = min((ULONG)clScanCount,
                        (pbhBitmap->Info.Height - lScanStart));

    if (lScanLinesGot == 0)
    {
        goto GETBITS_EXIT;
    }

    /******************************************************************/
    /* Set up the initial values                                      */
    /******************************************************************/
    ptlStartPoint.x = 0;
    ptlStartPoint.y = lScanStart;

    pAddress = pArgAddress;
    pInfo    = pArgInfo;

    /**************************************************************/
    /* Fill in the width and height in the Bitmap info table.     */
    /**************************************************************/
    if ( OldFormatBitmap(pArgInfo) )
    {
       ((PBITMAPINFO)pArgInfo)->cx = (USHORT)pbhBitmap->Info.Width;
       ((PBITMAPINFO)pArgInfo)->cy = (USHORT)lScanLinesGot;
    }
    else /* new format header */
    {
       pArgInfo->cx = pbhBitmap->Info.Width;
       pArgInfo->cy = lScanLinesGot;
    }

    /**********************************************************/
    /* If a compressed format is being asked for we won't     */
    /* have enough memory since we can only get               */
    /* uncompressed. Go and get an info header and bitmap     */
    /* that we can put the uncompressed data into.            */
    /**********************************************************/
    pInfo = MemoryForUncompressedBM(pArgInfo, &pAddress);
    if ( pInfo == NULL )
    {
       lScanLinesGot = GPI_ALTERROR;
       goto GETBITS_EXIT;
    }

    /**************************************************************/
    /* Keep a note of whether compression is needed or not.       */
    /**************************************************************/
    if (pArgInfo != pInfo)
    {
        fCompression = TRUE;
    }

    /**************************************************************/
    /* Transfer bits to application storage from the bitmap using */
    /* a conversion function.                                     */
    /* We first get the bits uncompressed, then if conversion is  */
    /* needed, we pass the bits on to the engine to be compressed.*/
    /**************************************************************/

    ConvertIntToExt(pAddress,
                    pInfo,
                    pbhBitmap,
                    &ptlStartPoint,
                    lScanLinesGot);

    if (fCompression)
    {
        if (GPI_OK != InnerGre32Entry9(pdc->DCIhdc,
                                       CBD_COMPRESSION,
                                       0L,
                                       pInfo,
                                       pAddress,
                                       pArgInfo,
                                       pArgAddress,
                                       0L,
                                       NGreConvertBitmapData) )
        {
            lScanLinesGot = GPI_ALTERROR;
        }
    }

GETBITS_EXIT:
    /******************************************************************/
    /* Free any temporary bitmap used for (de)compression.            */
    /******************************************************************/
    if (fCompression)
    {
        FreeMemory(pInfo);
    }

    /******************************************************************/
    /* Raise any error needed.                                        */
    /******************************************************************/
    CheckForErrors();

    ExitDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);

    return(lScanLinesGot);

} /* GetBitmapBits */


/**********************************************************************/
/*                                                                    */
/*   SetBitmapBits transfers data from application storage to the     */
/* given bitmap.  It is only valid for a Memory DC. If the given      */
/* bitmap handle is null then the currently selected bitmap in the    */
/* given DC is used (an error is returned if there is no currently    */
/* selected bitmap in the given DC).                                  */
/*                                                                    */
/*   The application defines the region of the bitmap to be set in    */
/* terms of a number of scanlines.  Scanline # 0 is taken             */
/* to be the bottom scanline (in the PM sense).                       */
/* Scanlines are numbered upward.  The actual number of scanlines     */
/* for which data is set is returned (this may be less than the       */
/* application requested).                                            */
/*                                                                    */
/*   The application gives the device driver two pointers; the        */
/* BitmapBits and a BitmapInfoTable with which to interpret these     */
/* bits.  The device driver returns an error if this does not         */
/* correspond to a standard PM format.                                */
/*                                                                    */
/*   SetBitmapBits is not subject to clipping.   The draw bit is      */
/* not tested.                                                        */
/*                                                                    */
/**********************************************************************/

DDIENTRY SetBitmapBits (HDC          hdc,
                        HBITMAP      hBitmap,
                        LONG         lScanStart,
                        LONG         clScanCount,
                        PBYTE        pArgAddress,
                        PBITMAPINFO2 pArgInfo,
                        PDC          pdcArg,
                        ULONG        FunN)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    pBitmapHeader       pbhBitmap;
    LONG                lScanLinesGot;
    BOOL                fCompression;
    PBITMAPINFO2        pInfo;
    PBYTE               pAddress;
    POINTL              ptlStartPoint;

    EnterDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);
    COMMANDBITS(FunN) &= pdc->DCICommandMask;

#ifdef FIREWALLS
    /******************************************************************/
    /* Check that the function number is SetBitmapBits                */
    /* Changes to the engine headers have previously caused problems. */
    /******************************************************************/
    if ( !FUNCTIONIS(FunN, NGreSetBitmapBits) )
    {
        DebugOutput("Invalid function number for SetBitmapBits!\r\n");
        haltproc();
    }
#endif

    /******************************************************************/
    /* Assume no conversion (compression or decompression) of the     */
    /* new format bitmap is needed.                                   */
    /******************************************************************/
    fCompression = FALSE;

    /******************************************************************/
    /* Get the bitmap header for the bitmap from which the bits are   */
    /* to be retrieved/set in to.                                     */
    /******************************************************************/
    pbhBitmap = GetBMHeader(hBitmap);

    /******************************************************************/
    /* Check parameter validity.                                      */
    /******************************************************************/
    if ( (pbhBitmap == NULL)                        ||
         IllegallyInPath(FunN)                      ||
         InvalidScanCount(clScanCount)              ||
         !ValidHeader(pArgInfo)                     ||
         ScanStartOutsideBM(lScanStart, pbhBitmap) )
    {
        lScanLinesGot = GPI_ALTERROR;
        goto SETBITS_EXIT;
    }

    /******************************************************************/
    /* Set up the number of scanlines to be obtained. This is not     */
    /* necessarily the number requested.                              */
    /* Leave function if Scan lines to be obtained is zero.           */
    /******************************************************************/
    lScanLinesGot = min((ULONG)clScanCount,
                        (pbhBitmap->Info.Height - lScanStart));

    if (lScanLinesGot == 0)
    {
        goto SETBITS_EXIT;
    }

    /******************************************************************/
    /* Set up the initial values                                      */
    /******************************************************************/
    ptlStartPoint.x = 0;
    ptlStartPoint.y = lScanStart;

    pAddress = pArgAddress;
    pInfo    = pArgInfo;

    /*************************************************************/
    /* Make sure we have memory to hold the external data in an  */
    /* uncompressed format.                                      */
    /*************************************************************/
    pInfo = MemoryForUncompressedBM(pArgInfo, &pAddress);
    if ( pInfo == NULL )
    {
        lScanLinesGot = GPI_ALTERROR;
        goto SETBITS_EXIT;
    }

    /**************************************************************/
    /* Keep a note of whether compression is needed or not.       */
    /**************************************************************/
    if (pArgInfo != pInfo)
    {
        fCompression = TRUE;
    }

    /**************************************************************/
    /* We have some memory which can hold the external data in    */
    /* uncompressed format. If the data passed is compressed      */
    /* we need to uncompress into our new memory. If the passed   */
    /* data is uncompressed then it is already at pArgAddress.       */
    /**************************************************************/
    if (fCompression)
    {
        /**********************************************************/
        /* Uncompress the bitmap before we use it                 */
        /**********************************************************/
        if (GPI_OK != InnerGre32Entry9(pdc->DCIhdc,
                                       CBD_DECOMPRESSION,
                                       0L,
                                       pArgInfo,
                                       pArgAddress,
                                       pInfo,
                                       pAddress,
                                       0L,
                                       NGreConvertBitmapData))
        {
            /******************************************************/
            /* Decompression failed.                              */
            /******************************************************/
            lScanLinesGot = GPI_ALTERROR;
            goto SETBITS_EXIT;
        }
    }

    /**************************************************************/
    /* DEFECT - 53634  (Joe Celi 9/14/92)                         */
    /*                                                            */
    /* If the target bitmap is cached then evict it since we are  */
    /* going to update the contents of it.                        */
    /**************************************************************/
    if ( BITMAP_IS_CACHED(pbhBitmap) )
      evict_cached_bitmap(pbhBitmap->bm_cache_slot);

    /**************************************************************/
    /* Now do the conversion.                                     */
    /**************************************************************/
    ConvertExtToInt(pAddress,
                    pInfo,
                    pbhBitmap,
                    &ptlStartPoint,
                    lScanLinesGot);

    /**************************************************************/
    /* Do the bounds if required.                                 */
    /**************************************************************/
    if (!CheckBounds(FunN,
                     pInfo,
                     ptlStartPoint,
                     lScanLinesGot,
                     pbhBitmap) )
    {
        lScanLinesGot = GPI_ALTERROR;
    }

SETBITS_EXIT:
    /******************************************************************/
    /* Free any temporary bitmap used for (de)compression.            */
    /******************************************************************/
    if (fCompression)
    {
        FreeMemory(pInfo);
    }

    /******************************************************************/
    /* Raise any error needed.                                        */
    /******************************************************************/
    CheckForErrors();

    ExitDriver(pdcArg, FunN, EDF_STANDARD | EDF_DONT_CLEAN);

    return(lScanLinesGot);

} /* SetBitmapBits */

/**********************************************************************/
/* CheckBounds                                                        */
/*                                                                    */
/* fsCommandBits  the command bits from the FunN passed into the      */
/*                driver                                              */
/*                                                                    */
/* pInfo          pointer to the users bitmap header                  */
/*                                                                    */
/* ptlStartPoint  scan start coordinate                               */
/*                                                                    */
/* clScanLines    count of the scan lines to be processed             */
/*                                                                    */
/* pbhBitmap      pointer to the xga header specifying the bitmap     */
/*                                                                    */
/* Determines if bounds need to be calculated and if so does it.      */
/* Returns TRUE if successful, FALSE otherwise.                       */
/**********************************************************************/

BOOL PASCAL CheckBounds(ULONG         fsCommandBits,
                        PBITMAPINFO2  pInfo,
                        POINTL        ptlStartPoint,
                        LONG          clScanLines,
                        pBitmapHeader pbhBitmap)
{
    RECTS rcsBounds;

    if ( fsCommandBits & (COM_BOUND | COM_ALT_BOUND) )
    {
        /**************************************************************/
        /* Left and bottom of bounds are simply the start point.      */
        /**************************************************************/
        rcsBounds.pts1.x = (SHORT)ptlStartPoint.x;
        rcsBounds.pts1.y = (SHORT)ptlStartPoint.y;

        if ( OldFormatBitmap(pInfo) )
        {
            /**********************************************************/
            /* Old format uses BITMAPINFO header.                     */
            /**********************************************************/
            rcsBounds.pts2.x = (SHORT)(ptlStartPoint.x - 1 +
                                   min(((PBITMAPINFO)pInfo)->cx,
                                       (USHORT)pbhBitmap->Info.Width));
        }
        else /* new format header */
        {
            /**********************************************************/
            /* We were already passed BITMAPINFO2 structure.          */
            /**********************************************************/
            rcsBounds.pts2.x = (SHORT)(ptlStartPoint.x - 1 +
                                 min(pInfo->cx, pbhBitmap->Info.Width));
        }

        rcsBounds.pts2.y = (SHORT)(ptlStartPoint.y + 1 - clScanLines);

        if ( OK != eddg_AddBounds((pDevRect)&rcsBounds,
                                  fsCommandBits,
                                  COORD_AI) )
        {
            return(FALSE);
        }

    } /* bounds are to be accumulated */

    return(TRUE);

} /* CheckBounds */


/**********************************************************************/
/* MemoryForUncompressedBitmap                                        */
/*                                                                    */
/* pInfo     pointer to a bitmap header                               */
/* ppBitmap  pointer to the pointer to the bitmap bits associated     */
/*           with pInfo                                               */
/*                                                                    */
/* Determines if the bitmap specified by pInfo is in compressed form. */
/* If not it returns the PBITMAPINFO passed as one suitable to use    */
/* for the bitmap. If it is compressed a new header and bitmap are    */
/* allocated and the address of this PBITMAPINFO is returned. The     */
/* address of the new bitmap bits is returned in ppBitmap.            */
/* Returns NULL if an error occurs.                                   */
/**********************************************************************/

PBITMAPINFO2 PASCAL MemoryForUncompressedBM(PBITMAPINFO2 pInfo,
                                            PBYTE *      ppbBitmap)
{
    if ( CompressedBitmap(pInfo) )
    {
        /**************************************************************/
        /* Input header says compressed so we need to allocate a      */
        /* block of memory which holds both the new BITMAPINFO2       */
        /* structure (specifying uncompressed) and the real external  */
        /* information including the color table and the bits.        */
        /**************************************************************/
        return (CreateExternalBitmap(pInfo,ppbBitmap));
    }
    else
    {
        /**************************************************************/
        /* Input header already is uncompressed.                      */
        /**************************************************************/
        return(pInfo);
    }

} /* MemoryForUncompressedBM */


/**********************************************************************/
/* ScanStartOutsideBM                                                 */
/*                                                                    */
/* lScanStart  number of the scan line at which the first data is to  */
/*             be got or set                                          */
/*                                                                    */
/* pbhBitmap   pointer to the header specifying the bitmap to be got  */
/*             from or set to                                         */
/*                                                                    */
/* Returns TRUE if the ScanStart lies outside the bitmap, FALSE       */
/* otherwise.                                                         */
/**********************************************************************/

BOOL PASCAL ScanStartOutsideBM(ULONG         lScanStart,
                               pBitmapHeader pbhBitmap)
{
    if ( lScanStart >= pbhBitmap->Info.Height )
    {
        eiErrorToLog = MAKEERRORID(SEVERITY_WARNING, PMERR_INV_SCAN_START);
        return(TRUE);
    }
    else
    {
        return(FALSE);
    }
} /* ScanStartOutsideBM */


/**********************************************************************/
/* InvalidScanCount                                                   */
/*                                                                    */
/* clScanCount  count of the number of scanlines to be got or set     */
/*                                                                    */
/* Returns TRUE if the ScanCount is outside the allowed range, FALSE  */
/* otherwise.                                                         */
/**********************************************************************/

BOOL PASCAL InvalidScanCount(LONG clScanCount)
{
    if ( (clScanCount > MAX_SCAN_COUNT) || (clScanCount < 0) )
    {
        eiErrorToLog = MAKEERRORID(SEVERITY_ERROR, PMERR_INV_LENGTH_OR_COUNT);
        return(TRUE);
    }
    else
    {
        return(FALSE);
    }
} /* InvalidScanCount */


/**********************************************************************/
/* GetBMHeader                                                        */
/*                                                                    */
/* hBitmap  a bitmap handle or NULL if the bitmap selected in the dc  */
/*          is to be used                                             */
/*                                                                    */
/* Gets a pointer to the bitmap header to be used for getting/setting */
/* bits; if hBitmap is NULL this is the bitmap selected in pdc,       */
/* otherwise it is the bitmap specified by hBitmap.                   */
/*                                                                    */
/* If hBitmap is NULL then pdc must be a memory dc and it must have a */
/* bitmap selected into it.                                           */
/*                                                                    */
/* Returns NULL and sets eiErrorToLog if an error is detected, or the */
/* pointer to the bitmap header if successful                         */
/**********************************************************************/

pBitmapHeader GetBMHeader(HBITMAP hBitmap)
{
    pBitmapHeader pbhBitmap;

    if ( hBitmap == NULL )
    {
        /**************************************************************/
        /* No bitmap handle was given so we must check out the one    */
        /* in the current DC.                                         */
        /**************************************************************/
        if (pdc->DCIDCType != (USHORT)OD_MEMORY)
        {
            /**********************************************************/
            /* Its an error if we are not a memory DC.                */
            /**********************************************************/
            eiErrorToLog = MAKEERRORID(SEVERITY_ERROR,
                                       PMERR_INCORRECT_DC_TYPE);
        }
        else if (pdc->DCIBitmapType & BITMAP_NOT_SELECTED)
        {
            /**********************************************************/
            /* An error if there is no bitmap selected in this DC.    */
            /**********************************************************/
            eiErrorToLog = MAKEERRORID(SEVERITY_ERROR,
                                       PMERR_NO_BITMAP_SELECTED);
        }
        else
        {
            /**********************************************************/
            /* No errors so use the bitmap in the DC.                 */
            /**********************************************************/
            return(pdc->DCISelListEntry);
        }
    }
    else
    {
        /**************************************************************/
        /* We were passed the bitmap handle, so get the Engine to     */
        /* convert it into a handle that the driver can understand.   */
        /**************************************************************/
        pbhBitmap = (pBitmapHeader)GetDriverInfo32(hBitmap,
                                                   DI_HBITMAP,
                                                   pdc->DCIhdc);

        if (pbhBitmap == (pBitmapHeader)(GPI_ALTERROR) )
        {
            /**********************************************************/
            /* Engine could not handle the passed handle, so raise    */
            /* error that the handle was in error.                    */
            /**********************************************************/
            eiErrorToLog = MAKEERRORID(SEVERITY_ERROR,
                                       PMERR_INV_HBITMAP);
        }
        else
        {
            /**********************************************************/
            /* Return the device bitmap handle the engine gave us.    */
            /**********************************************************/
            return(pbhBitmap);
        }
    }

    /******************************************************************/
    /* All successful branches return, so to reach here we must have  */
    /* been unsuccessful.                                             */
    /******************************************************************/
    return(NULL);

} /* GetBMHeader */
