Ejemplo n.º 1
0
PBRUSH
NTAPI
PEN_AllocExtPenWithHandle(
    VOID)
{
    PPEN ppen;

    ppen = (PBRUSH)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_EXTPEN_TYPE, sizeof(PEN));
    if (ppen == NULL)
    {
        return NULL;
    }

    PEN_vInit(ppen);
    return ppen;
}
Ejemplo n.º 2
0
PSURFACE
NTAPI
SURFACE_AllocSurface(
    _In_ USHORT iType,
    _In_ ULONG cx,
    _In_ ULONG cy,
    _In_ ULONG iFormat,
    _In_ ULONG fjBitmap,
    _In_opt_ ULONG cjWidth,
    _In_opt_ ULONG cjBufSize,
    _In_opt_ PVOID pvBits)
{
    ULONG cBitsPixel, cjBits, cjObject;
    PSURFACE psurf;
    SURFOBJ *pso;
    PVOID pvSection;

    NT_ASSERT(!pvBits || (iType == STYPE_BITMAP));
    NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0));
    NT_ASSERT((LONG)cy > 0);

    /* Verify format */
    if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG))
    {
        DPRINT1("Invalid bitmap format: %lu\n", iFormat);
        return NULL;
    }

    /* Get bits per pixel from the format */
    cBitsPixel = gajBitsPerFormat[iFormat];

    /* Are bits and a width in bytes given? */
    if (pvBits && cjWidth)
    {
        /* Align the width (Windows compatibility, drivers expect that) */
        cjWidth = WIDTH_BYTES_ALIGN32((cjWidth << 3) / cBitsPixel, cBitsPixel);
    }
    else
    {
        /* Calculate width from the bitmap width in pixels */
        cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel);
    }

    /* Is this an uncompressed format? */
    if (iFormat <= BMF_32BPP)
    {
        /* Calculate the correct bitmap size in bytes */
        if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits)))
        {
            DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n",
                    cjWidth, cy);
            return NULL;
        }

        /* Did we get a buffer and size? */
        if ((pvBits != NULL) && (cjBufSize != 0))
        {
            /* Make sure the buffer is large enough */
            if (cjBufSize < cjBits)
            {
                DPRINT1("Buffer is too small, required: %lu, got %lu\n",
                        cjBits, cjBufSize);
                return NULL;
            }
        }
    }
    else
    {
        /* Compressed format, use the provided size */
        NT_ASSERT(cjBufSize != 0);
        cjBits = cjBufSize;
    }

    /* Check if we need an extra large object */
    if ((iType == STYPE_BITMAP) && (pvBits == NULL) &&
        !(fjBitmap & BMF_USERMEM) && !(fjBitmap & BMF_KMSECTION))
    {
        /* Allocate an object large enough to hold the bits */
        cjObject = sizeof(SURFACE) + cjBits;
    }
    else
    {
        /* Otherwise just allocate the SURFACE structure */
        cjObject = sizeof(SURFACE);
    }

    /* Check for arithmetic overflow */
    if (cjObject < sizeof(SURFACE))
    {
        /* Fail! */
        DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits);
        return NULL;
    }

    /* Allocate a SURFACE object */
    psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, cjObject);
    if (!psurf)
    {
        return NULL;
    }

    /* Initialize the basic fields */
    pso = &psurf->SurfObj;
    pso->hsurf = psurf->BaseObject.hHmgr;
    pso->sizlBitmap.cx = cx;
    pso->sizlBitmap.cy = cy;
    pso->iBitmapFormat = iFormat;
    pso->iType = iType;
    pso->fjBitmap = (USHORT)fjBitmap;
    pso->iUniq = InterlockedIncrement(&giUniqueSurface);
    pso->cjBits = cjBits;

    /* Check if we need a bitmap buffer */
    if (iType == STYPE_BITMAP)
    {
        /* Check if we got one or if we need to allocate one */
        if (pvBits != NULL)
        {
            /* Use the caller provided buffer */
            pso->pvBits = pvBits;
        }
        else if (fjBitmap & BMF_USERMEM)
        {
            /* User mode memory was requested */
            pso->pvBits = EngAllocUserMem(cjBits, 0);

            /* Check for failure */
            if (!pso->pvBits)
            {
                GDIOBJ_vDeleteObject(&psurf->BaseObject);
                return NULL;
            }
        }
        else if (fjBitmap & BMF_KMSECTION)
        {
            /* Use a kernel mode section */
            pso->pvBits = EngAllocSectionMem(&pvSection,
                                             (fjBitmap & BMF_NOZEROINIT) ?
                                                 0 : FL_ZERO_MEMORY,
                                             cjBits, TAG_DIB);

            /* Check for failure */
            if (!pso->pvBits)
            {
                GDIOBJ_vDeleteObject(&psurf->BaseObject);
                return NULL;
            }

            /* Free the section already, but keep the mapping */
            EngFreeSectionMem(pvSection, NULL);
        }
        else
        {
            /* Buffer is after the object */
            pso->pvBits = psurf + 1;

            /* Zero the buffer, except requested otherwise */
            if (!(fjBitmap & BMF_NOZEROINIT))
            {
                RtlZeroMemory(pso->pvBits, cjBits);
            }
        }

        /* Set pvScan0 and lDelta */
        if (fjBitmap & BMF_TOPDOWN)
        {
            /* Topdown is the normal way */
            pso->pvScan0 = pso->pvBits;
            pso->lDelta = cjWidth;
        }
        else
        {
            /* Inversed bitmap (bottom up) */
            pso->pvScan0 = ((PCHAR)pso->pvBits + pso->cjBits - cjWidth);
            pso->lDelta = -(LONG)cjWidth;
        }
    }
    else
    {
        /* There are no bitmap bits */
        pso->pvScan0 = pso->pvBits = NULL;
        pso->lDelta = 0;
    }

    /* Assign a default palette and increment its reference count */
    SURFACE_vSetPalette(psurf, appalSurfaceDefault[iFormat]);

    return psurf;
}