Hello,
To begin with, I’m aware of the diminishing prevalence of mirror drivers - this is more of a learning exercise than anything. I’ve implemented a mirror driver, loosely based off of the DDK example. This only implements the routines for a remote display driver and no others, and renders to a shared memory map file that is consumed in a user-mode application. Changes are tracked using a combination of the DrvEscape routine and the same shared memory used for the framebuffer.
The question relates to the DrvBitBlt routine. I use this to populate an internal buffer of changes, later consumed by a user-mode application. In that routine, if the CLIPOBJ (pco) is NULL, then I just populate the changes buffer with the prclDst RECTL, otherwise, the following routine is called, utilising the iDComplexity field to determine the clipping regions. EngBitBlt is finally called too. This works well and as expected for the vast majority of changes, but doesn’t seem to correctly identify changes in the title bar in Windows 7. All changes are rendered on a surface in a user-mode app; however, the image linked below shows the result of maximising a window - part of the title bar is cut off. The black part shown is the black desktop wallpaper that was previously visible. Hovering over or clicking the minimise, maximise or close buttons aren’t detected either.
Example of the issue:
https://imgur.com/a/MDFMDqX
Any help is greatly appreciated. Thanks,
Jamie
The code in question:
VOID AddClipRegion(
INTERNAL_CHANGES_BUFFER* cb,
CLIPOBJ* pco,
RECTL* dest)
{
if (!pco)
{
return;
}
switch (pco->iDComplexity)
{
case DC_TRIVIAL:
{
// The clip region is not used, add the destination bounds as is.
AddChange(cb, dest);
break;
}
case DC_RECT:
{
// There is one clip region.
RECTL bounds = { 0 };
bounds.left = dest->left;
bounds.right = dest->right;
bounds.top = dest->top;
bounds.bottom = dest->bottom;
if (bounds.left < pco->rclBounds.left)
{
bounds.left = pco->rclBounds.left;
}
if (bounds.right > pco->rclBounds.right)
{
bounds.right = pco->rclBounds.right;
}
if (bounds.top < pco->rclBounds.top)
{
bounds.top = pco->rclBounds.top;
}
if (bounds.bottom > pco->rclBounds.bottom)
{
bounds.bottom = pco->rclBounds.bottom;
}
if ((bounds.right - bounds.left) <= 0 || (bounds.bottom - bounds.top) <= 0)
{
return;
}
AddChange(cb, &bounds);
break;
}
case DC_COMPLEX:
{
BOOL overflow;
ENUMRECTS crs;
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
do
{
overflow = CLIPOBJ_bEnum(pco, sizeof(crs), (ULONG*)&crs);
for (RECTL* cr = &crs.arcl[0]; crs.c != 0; cr++, crs.c--)
{
RECTL bounds = { 0 };
bounds.left = dest->left;
bounds.right = dest->right;
bounds.top = dest->top;
bounds.bottom = dest->bottom;
if (bounds.left < cr->left)
{
bounds.left = cr->left;
}
if (bounds.right > cr->right)
{
bounds.right = cr->right;
}
if (bounds.top < cr->top)
{
bounds.top = cr->top;
}
if (bounds.bottom > cr->bottom)
{
bounds.bottom = cr->bottom;
}
if ((bounds.right - bounds.left) <= 0 || (bounds.bottom - bounds.top) <= 0)
{
continue;
}
AddChange(cb, &bounds);
}
} while (overflow);
break;
}
}
}