Display Mirror Driver

Hi,

Could someone give me a brief background into the display mirror driver. I’ve looked at the WDK code and so far I have written a communication between a user app and the dll using Memory Mapping, and I am understanding a lot.

The problem I am facing is that everything that is being sent to the driver is also being picked up by the mirror. This is obvious, what I am keen on knowing is how can I filter only the information that is being drawn on the screen. Could it be that I am using the wrong desktop? (Even though I don’t have many doubts that I am.)

Thanks as always,

xxxxx@hotmail.com wrote:

Could someone give me a brief background into the display mirror driver. I’ve looked at the WDK code and so far I have written a communication between a user app and the dll using Memory Mapping, and I am understanding a lot.

The problem I am facing is that everything that is being sent to the driver is also being picked up by the mirror. This is obvious, what I am keen on knowing is how can I filter only the information that is being drawn on the screen. Could it be that I am using the wrong desktop? (Even though I don’t have many doubts that I am.)

I don’t understand what you’re asking. The purpose of a mirror driver
is exactly what you described – it gets a copy of all commands sent to
the main desktop, so that it can maintain its own independent copy of
the desktop. It is a “mirror” copy.

What are you actually trying to do?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I’m backwards engineering a remote desktop protocol and sending the desktop image to a client app.

In that case I don’t understand the results I have. Since I have pictures of large questionmarks and sprites that don’t seem to appear on any window.

xxxxx@hotmail.com wrote:
> Could someone give me a brief background into the display mirror driver. I’ve
looked at the WDK code and so far I have written a communication between a user
app and the dll using Memory Mapping, and I am understanding a lot.
>
> The problem I am facing is that everything that is being sent to the driver is
also being picked up by the mirror. This is obvious, what I am keen on knowing
is how can I filter only the information that is being drawn on the screen.
Could it be that I am using the wrong desktop? (Even though I don’t have many
doubts that I am.)

I don’t understand what you’re asking. The purpose of a mirror driver
is exactly what you described – it gets a copy of all commands sent to
the main desktop, so that it can maintain its own independent copy of
the desktop. It is a “mirror” copy.

What are you actually trying to do?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Take a look at this:

http://www.codeproject.com/KB/system/driverdev6asp.aspx

On Oct 5, 2010, at 3:09 PM, xxxxx@hotmail.com wrote:

Hi,

Could someone give me a brief background into the display mirror driver. I’ve looked at the WDK code and so far I have written a communication between a user app and the dll using Memory Mapping, and I am understanding a lot.

The problem I am facing is that everything that is being sent to the driver is also being picked up by the mirror. This is obvious, what I am keen on knowing is how can I filter only the information that is being drawn on the screen. Could it be that I am using the wrong desktop? (Even though I don’t have many doubts that I am.)

Thanks as always,


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

And this (among others), if you actually mean ‘RDP:’

http://msdn.microsoft.com/en-us/library/cc240445(PROT.10).aspx

Good luck,

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of John Dumais
Sent: Tuesday, October 05, 2010 5:51 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Display Mirror Driver

Take a look at this:

http://www.codeproject.com/KB/system/driverdev6asp.aspx

On Oct 5, 2010, at 3:09 PM, xxxxx@hotmail.com wrote:

Hi,

Could someone give me a brief background into the display mirror driver.
I’ve looked at the WDK code and so far I have written a communication
between a user app and the dll using Memory Mapping, and I am understanding
a lot.

The problem I am facing is that everything that is being sent to the
driver is also being picked up by the mirror. This is obvious, what I am
keen on knowing is how can I filter only the information that is being drawn
on the screen. Could it be that I am using the wrong desktop? (Even though I
don’t have many doubts that I am.)

Thanks as always,


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

When your mirror driver gets called, you get a bounding rectangle telling you what regions are being redrawn. You’ll need to keep a list of regions that have changed since the last update. On the first update the change list will have one entry bounding the entire screen.

You need to be aware that the mirror driver only gets called for call that originate with GDI. OpenGL and Direct won’t fire you mirror driver. You’ll need to hook those API’s some other way.

On Oct 5, 2010, at 3:09 PM, xxxxx@hotmail.com wrote:

> Hi,
>
> Could someone give me a brief background into the display mirror driver. I’ve looked at the WDK code and so far I have written a communication between a user app and the dll using Memory Mapping, and I am understanding a lot.
>
> The problem I am facing is that everything that is being sent to the driver is also being picked up by the mirror. This is obvious, what I am keen on knowing is how can I filter only the information that is being drawn on the screen. Could it be that I am using the wrong desktop? (Even though I don’t have many doubts that I am.)
>
> Thanks as always,
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Why not use RDP? It’s a whole lot easier than writing a mirror driver and figuring out how to hook OpenGL, Direct, etc.

On Oct 5, 2010, at 3:42 PM, xxxxx@hotmail.com wrote:

> I’m backwards engineering a remote desktop protocol and sending the desktop image to a client app.
>
> In that case I don’t understand the results I have. Since I have pictures of large questionmarks and sprites that don’t seem to appear on any window.
>
>> xxxxx@hotmail.com wrote:
>>> Could someone give me a brief background into the display mirror driver. I’ve
>> looked at the WDK code and so far I have written a communication between a user
>> app and the dll using Memory Mapping, and I am understanding a lot.
>>>
>>> The problem I am facing is that everything that is being sent to the driver is
>> also being picked up by the mirror. This is obvious, what I am keen on knowing
>> is how can I filter only the information that is being drawn on the screen.
>> Could it be that I am using the wrong desktop? (Even though I don’t have many
>> doubts that I am.)
>>
>> I don’t understand what you’re asking. The purpose of a mirror driver
>> is exactly what you described – it gets a copy of all commands sent to
>> the main desktop, so that it can maintain its own independent copy of
>> the desktop. It is a “mirror” copy.
>>
>> What are you actually trying to do?
>>
>> –
>> Tim Roberts, xxxxx@probo.com
>> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hi.

I am not trying to hook OpenGL or Direct, it is only the Windows Desktop I would like to capture.

I assume with RDP you mean use somebody else’ protocol. I would rather learn how to do it myself.

I’ve read through the links and I don’t understand is how to process the data and take an image from it.

case BMF_32BPP:
{
unsigned long i, k, w;
DbgPrint(“BMF_32BPP.\n”);
DbgPrint(“(%d, %d)-(%d, %d)\n”, x, y, Width, Height);
for(i=0, k=x, w=0; i < psoSrc->cjBits; i+=4, k+=4, w++)
{
if(k+4 <= pVideoMemorySize)
{
if(w >= (unsigned long) Width)
{
k = ((resolution.Width * 4) * (++y)) + x; w=0;
}
memcpy((unsigned char*) pVideoMemory + 54 + k, pvBits + i, 4);
}
else
{
DbgPrint(“Over, %d %d %d %d %d %d.\n”, k, psoSrc->cjBits, i, resolution.Width, y, x);
}
}
break;
}

If you use a mirror driver and the desktop houses an OpenGL or DirectX (directDraw, whatever) application, you won’t capture those applications. Your remote display will have holes in it.

RDP means Remote Desktop Protocol. It’s pretty much the standard used to remotely display a desktop. It’s available on most every desktop platform and does not have the problem of leaving holes a mirror driver will.

On Oct 6, 2010, at 4:42 AM, xxxxx@hotmail.com wrote:

Hi.

I am not trying to hook OpenGL or Direct, it is only the Windows Desktop I would like to capture.

I assume with RDP you mean use somebody else’ protocol. I would rather learn how to do it myself.

I’ve read through the links and I don’t understand is how to process the data and take an image from it.

case BMF_32BPP:
{
unsigned long i, k, w;
DbgPrint(“BMF_32BPP.\n”);
DbgPrint(“(%d, %d)-(%d, %d)\n”, x, y, Width, Height);
for(i=0, k=x, w=0; i < psoSrc->cjBits; i+=4, k+=4, w++)
{
if(k+4 <= pVideoMemorySize)
{
if(w >= (unsigned long) Width)
{
k = ((resolution.Width * 4) * (++y)) + x; w=0;
}
memcpy((unsigned char*) pVideoMemory + 54 + k, pvBits + i, 4);
}
else
{
DbgPrint(“Over, %d %d %d %d %d %d.\n”, k, psoSrc->cjBits, i, resolution.Width, y, x);
}
}
break;
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Think of their track record. Having government manage your healthcare is like having Michael Vick watch your dog.

Hi,

I suppose what I could do is write RDP into the service and look into a mirror driver at another date.

I assume when you mean holes you mean large areas of black. (Almost like the ScreenPrint button being pressed while running a Media Video.)

I will one day come back to this and have the same hurdles to jump. If I can’t use RDP for some reason I may be back sooner than I think. Thankyou though, I will try the direction you set out.

  • I would laugh at your signature but our government does manage our healthcare ; )

xxxxx@hotmail.com wrote:

I am not trying to hook OpenGL or Direct, it is only the Windows Desktop I would like to capture.

Have you looked at VNC to see how they do it? If not, then you haven’t
really done your homework at all. VNC includes 3 or 4 different
algorithms for getting copies of the desktop, including the low-tech but
perfectly functional option of doing a periodic BitBlt from a normal
user-mode application to take a copy of the desktop window and scan it
for differences. No driver required.

I assume with RDP you mean use somebody else’ protocol.

Microsoft’s protocol. (Formerly Citrix’s protocol.)

I would rather learn how to do it myself.

Microsoft and Citrix have invested 15 years into this product. Do not
underestimate the complexity of getting it right.

A mirror driver is a full-fledged Windows display driver. To understand
them, you need to understand display drivers, and that is very
complicated topic.

I’ve read through the links and I don’t understand is how to process the data and take an image from it.

case BMF_32BPP:
{
unsigned long i, k, w;
DbgPrint(“BMF_32BPP.\n”);
DbgPrint(“(%d, %d)-(%d, %d)\n”, x, y, Width, Height);
for(i=0, k=x, w=0; i < psoSrc->cjBits; i+=4, k+=4, w++)
{
if(k+4 <= pVideoMemorySize)
{
if(w >= (unsigned long) Width)
{
k = ((resolution.Width * 4) * (++y)) + x; w=0;
}
memcpy((unsigned char*) pVideoMemory + 54 + k, pvBits + i, 4);
}
else
{
DbgPrint(“Over, %d %d %d %d %d %d.\n”, k, psoSrc->cjBits, i, resolution.Width, y, x);
}
}
break;
}

Where’d you get that code? It is crap, and it makes several invalid
assumptions. Is that inside DrvCopyBits?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi,

I am beginning to believe you.

The problem I faced, is I am using a service in Vista to obtain a copy of the desktop and switching between desktops isn’t advisable for security reasons. So I wanted a better approach and a faster one too. (For example only obtaining the areas of the desktop that had changed, rather than the whole static image and then XOR the results with the last desktop, as one project I read wrote it.)

The BitBlt approach was the one I had the most problems with, it gave me the Vista Service Desktop and not the User Desktop. There were suggestions to use a usermode application but I wanted something which was more containable. I didn’t want to run an external application everytime I wanted to take a image of the screen. So my next step was to read into a mirror driver. I’ve written filters before but this is the first time I have attempted doing something with the display.

DrvBltBit, the code was something I threw together to see what was going on. It saves the data to a MemoryMappedFile in a bitmap format.

xxxxx@hotmail.com wrote:

The problem I faced, is I am using a service in Vista to obtain a copy of the desktop and switching between desktops isn’t advisable for security reasons.

Yes. The concept of “THE desktop” is quite problematic in Vista. There
are many desktops. Which one is THE desktop? What if they used “fast
user switching”, so that several people are logged on at once? Which
one will you get?

So I wanted a better approach and a faster one too. (For example only obtaining the areas of the desktop that had changed, rather than the whole static image and then XOR the results with the last desktop, as one project I read wrote it.)

The BitBlt approach was the one I had the most problems with, it gave me the Vista Service Desktop and not the User Desktop. There were suggestions to use a usermode application but I wanted something which was more containable. I didn’t want to run an external application everytime I wanted to take a image of the screen. So my next step was to read into a mirror driver. I’ve written filters before but this is the first time I have attempted doing something with the display.

DrvBltBit, the code was something I threw together to see what was going on. It saves the data to a MemoryMappedFile in a bitmap format.

You’re not thinking in two dimensions. You need to do a loop in Y, then
in X. You’re saving the entire source bitmap, without regard to what
part of the source bitmap is being used in this call. You’re assuming
the source bitmap has contiguous scanlines with no padding. And where
did the constant “54” come from?

If the source and destination are both 32 bpp, the inner loop (in X) can
be done as a memmove. So, you end up with something like this:

dstStride = psoDest->lDelta;
srcStride = psoSrc->lDelta;
for( int y = 0; y < height; y++ )
{
RtlMoveMemory( pDst, pSrc, width * 4 );
pDst += dstStride;
pSrc += srcStride;
}


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi,

The MemoryMappedFile is a bitmap image, the constant 54 is the length of the BITMAP Header. It is only for fast debugging. (The driver is unloaded after a test and I only double-click the BITMAP to load it.)

The only desktop that is required, is the local which I may be assuming wrongly, so could you correct me would always be the first user desktop. (First is the Service, Second is the user.) Is there a way of identifying which desktop you are using, local / remote logged in?

I didn’t think about it sending an image inside an image. I assumed that padding wouldn’t be needed because the width was always going to be a multiple of 4 bytes since the BPP is 32bit. If I were saving or reading from a 24bit image I would have written some padding code.

You have cleared a few things up. Which variable would I use to determine which part of the bitmap was being used?

xxxxx@hotmail.com wrote:

The MemoryMappedFile is a bitmap image, the constant 54 is the length of the BITMAP Header. It is only for fast debugging. (The driver is unloaded after a test and I only double-click the BITMAP to load it.)

Ah; I usually use sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER).

The only desktop that is required, is the local which I may be assuming wrongly, so could you correct me would always be the first user desktop. (First is the Service, Second is the user.) Is there a way of identifying which desktop you are using, local / remote logged in?

You can have several people logged on locally to a single computer, if
“fast user switching” is enabled. Each one gets a desktop. Have you
never seen the “Switch User” option on the same menu as Log Off and
Shutdown?

I didn’t think about it sending an image inside an image. I assumed that padding wouldn’t be needed because the width was always going to be a multiple of 4 bytes since the BPP is 32bit. If I were saving or reading from a 24bit image I would have written some padding code.

What I meant is that the width of the BitBlt is not necessary the same
as the width of the source bitmap. I can blit a piece of one window to
another part of the window.

You have cleared a few things up. Which variable would I use to determine which part of the bitmap was being used?

Have you done graphics programming where you have used the BitBlt call?
Remember that BitBlt is not only used to copy between windows and
bitmaps, it’s also used to blend windows and bitmaps, and to draw solid
colors.

The width and height of the section to transfer is in prclTrg
(intersected with the clipping region in pco, when given). The starting
point within the source bitmap is pptlSrc. Note, however, that some
ROPs don’t use the source at all. You have to look at the ROP4 to
figure that out.

In general, you shouldn’t need to look at the source bitmap or the
pattern. What you do is pass the call to EngBitBlt, let it do the
drawing on your copy of the desktop, then figure out what part of your
desktop was changed by the call, and save that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi,

Thanks Tim, I’ll implentment the changes you have suggested and get back in a couple of days to let you know how I got on. I assume once I run EngBitBlt the I am looking at SURFOBJ *psoDst.

Thanks as always.

xxxxx@hotmail.com wrote:

Thanks Tim, I’ll implentment the changes you have suggested and get back in a couple of days to let you know how I got on. I assume once I run EngBitBlt the I am looking at SURFOBJ *psoDst.

Well, you’ll get BitBlt calls to transfer FROM your surface as well as
BitBlt calls to transfer TO your surface. You need to check the dhsurf
to know which is which. If it’s a transfer FROM your surface, then
nothing is being updated.

You can either get the pvBits from the SURFOBJ, or you can store a
pointer to your surface in your PPDEV structure and get it from there.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Also, you might want to check out nomachine nx. Much better than vnc, I
think.

That being said, I have no idea why you’re doing this at all.

Mm

On Oct 6, 2010 1:31 PM, “Tim Roberts” wrote:
> xxxxx@hotmail.com wrote:
>> I am not trying to hook OpenGL or Direct, it is only the Windows Desktop
I would like to capture.
>
> Have you looked at VNC to see how they do it? If not, then you haven’t
> really done your homework at all. VNC includes 3 or 4 different
> algorithms for getting copies of the desktop, including the low-tech but
> perfectly functional option of doing a periodic BitBlt from a normal
> user-mode application to take a copy of the desktop window and scan it
> for differences. No driver required.
>
>> I assume with RDP you mean use somebody else’ protocol.
>
> Microsoft’s protocol. (Formerly Citrix’s protocol.)
>
>> I would rather learn how to do it myself.
>
> Microsoft and Citrix have invested 15 years into this product. Do not
> underestimate the complexity of getting it right.
>
> A mirror driver is a full-fledged Windows display driver. To understand
> them, you need to understand display drivers, and that is very
> complicated topic.
>
>> I’ve read through the links and I don’t understand is how to process the
data and take an image from it.
>>
>> case BMF_32BPP:
>> {
>> unsigned long i, k, w;
>> DbgPrint(“BMF_32BPP.\n”);
>> DbgPrint(“(%d, %d)-(%d, %d)\n”, x, y, Width, Height);
>> for(i=0, k=x, w=0; i < psoSrc->cjBits; i+=4, k+=4, w++)
>> {
>> if(k+4 <= pVideoMemorySize)
>> {
>> if(w >= (unsigned long) Width)
>> {
>> k = ((resolution.Width * 4) * (++y)) + x; w=0;
>> }
>> memcpy((unsigned char*) pVideoMemory + 54 + k, pvBits + i, 4);
>> }
>> else
>> {
>> DbgPrint(“Over, %d %d %d %d %d %d.\n”, k, psoSrc->cjBits, i,
resolution.Width, y, x);
>> }
>> }
>> break;
>> }
>
> Where’d you get that code? It is crap, and it makes several invalid
> assumptions. Is that inside DrvCopyBits?
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi Tim,

I have done as you have suggested and I would like to know something. What conditions would cause psoDst->cjBits > 0 and psoDst->pvBits == NULL?

if (!EngBitBlt(psoDst, psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc, pptlMask, pbo, pptlBrush, rop4))
{
DbgPrint(“EngBitBlt failed.\n”);
}

I’ve included the line above because it seems like it isn’t being called properly. Is there a way of knowig which desktop I am collecting from? I am receiving a blank screen, (previously was a copy of the desktop.) with images of question marks and the non-digital clock showing the correct time.

Thanks.

Hi mm.

I would like 1) to learn and the other more practical reason is I would like a copy of a desktop image (no OpenGL or DirectX.) which I can obtain within a service from Vista and Windows 7. I will look at it.

xxxxx@hotmail.com wrote:

Hi Tim,

I have done as you have suggested and I would like to know something. What conditions would cause psoDst->cjBits > 0 and psoDst->pvBits == NULL?

You would get that it you told GDI that you had a “device managed
surface” by calling EngCreateDeviceSurface during initialization. In
that case, you are telling GDI that your surface does not look like a
DIB, so it can’t be treated like memory. Because of that, it can’t set
up a pvBits in the SURFOBJ. The assumption is that YOU will keep a
private bitmap somewhere, probably with a pointer in your PPDEV. GDI
hands you that, and you are expected to find the memory yourself.

That’s often NOT what you want for a mirror driver, because you want GDI
to be able to do your drawing. In that case, you probably want
EngCreateBitmap.

if (!EngBitBlt(psoDst, psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc, pptlMask, pbo, pptlBrush, rop4))
{
DbgPrint(“EngBitBlt failed.\n”);
}

I’ve included the line above because it seems like it isn’t being called properly. Is there a way of knowig which desktop I am collecting from? I am receiving a blank screen, (previously was a copy of the desktop.) with images of question marks and the non-digital clock showing the correct time.

If your surface is device-managed, then you cannot call back into GDI to
do the drawing. You have to do the drawing yourself. I suspect that’s
your biggest problem right now.

I would like 1) to learn and the other more practical reason is I would like a copy of a desktop image (no OpenGL or DirectX.) which I can obtain within a service from Vista and Windows 7. I will look at it.

Not from within a service. Services run in a session that does not have
access to the graphics device.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.