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; }
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; }