0

How does window compositing in the DWM (Windows 7+) work? Does the DWM ask each window what it looks like, and then composites those together onto the window frame and then onto the desktop? (And if so, what API call does it make when it asks? Could you respond with garbage?)

Or does it know that "Window A" is made up of a textbox at (5, 10) that is colored red, and it knows how to draw it accordingly? If that's the case, is there a API to tell the DWM what a window has?

Basically how does it go from an application (window) to what it draws on the screen? And what are the specific API calls (from the user app to the Windows DWM)?

Jason
  • 13,563
  • 15
  • 74
  • 125
  • This is a broad subject, its unclear at what level you want an answer. [Painting the Window](https://msdn.microsoft.com/en-gb/library/windows/desktop/ff381401(v=vs.85).aspx) – Alex K. Apr 25 '16 at 12:33
  • What's behind the question? I'm finding it hard to think of a scenario where these details would matter to an app developer. – David Heffernan Apr 25 '16 at 12:44
  • Alex K. Looking for answers to the questions in bold at the end. – Jason Apr 25 '16 at 12:46
  • David Heffernan: I'm looking to capture/modify what gets sent to the DWM for rendering. Not sure exactly what the process is, so trying to learn that first. – Jason Apr 25 '16 at 12:48
  • @AlexK. is BeginPaint still how it's done in Windows 7+? I didn't know if new WPF applications used something newer than GDI. – Jason Apr 25 '16 at 12:52
  • Why would you need to do that? Sounds like you haven't got the right solution to the problem. – David Heffernan Apr 25 '16 at 13:16
  • @DavidHeffernan Trying to capture a screenshot of an occluded window. ScreenCapture functions only capture what's on the screen. Getting the device context and forcing the window to paint to an offscreen context with PrintWindow is not well supported after XP. Hoping that I can hook User32 to get the intermediary. – Jason Apr 25 '16 at 13:28
  • If I were you I'd ask about your goal rather than your solution, because I'm sceptical that your solution is actually viable – David Heffernan Apr 25 '16 at 13:30
  • And having a distinct answer to this question would help me assess viability :) – Jason Apr 25 '16 at 13:52
  • 1
    The points we are trying to make are a) that an assessment of the viability can come as part of the overall discussion related to your end goal, and b) that there are other options that should also be tried first. You are asking for the entire Encyclopedia DWMitannica when in reality you only want volume Sa-Sc; let's focus on the problem you are trying to solve and we can solve your problem faster and with code that will be more robust. (The kind of fallacy that you have fallen into is a common problem called the "XY problem". If anyone comes off as abrasive, that is why.) – andlabs Apr 25 '16 at 14:37
  • (Actually this is a variation of the XY problem that seems to be unique to Stack Overflow that I can best describe as "I want [this](http://img.labnol.org/di/wikipedia-print.jpg)" "You don't want that, your question shows you really want [only this](http://aircollection.org/part/MHS/MD-83_1/casc-club_MHSMD-83Rev%2011.jpg)" — I'm not sure whether it has a name, or if not, what to call it...) – andlabs Apr 25 '16 at 14:52
  • Jason @andlabs makes good points. In any case, the question you asked is too broad and if you don't want to narrow the focus then I think it should be closed. – David Heffernan Apr 25 '16 at 15:35
  • Do you really need answers to all those questions in order to use [DWM Thumbnails](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969541.aspx)? – IInspectable Apr 26 '16 at 20:23
  • I'm not sure why you guys think I'm not asking the question I want an answer to. I've already done enough research to know that there's not a built in function to do what I want to do. I need more information to figure out the next steps. @Iinspectable DWM Thumbnails does not work for windows that are occluded or partially off screen. – Jason May 02 '16 at 13:01
  • @Jason: DWM thumbnails is the implementation used to display the taskbar thumbnail preview images. They render for any window, visible partially occluded, or offscreen. Why do you assume that this API wouldn't work for those windows? – IInspectable May 02 '16 at 13:08
  • @Jason it's because they don't know the answer, very few people do. The fact it's been 6 years without an answer attests that fact – Lewis Kelsey Jul 01 '22 at 02:33

1 Answers1

0

user32!CreateWindowExW eventually calls user32!NtUserCreateWindowEx, which is a win32k syscall. It ends up calling win32k!xxxCreateWindowEx, which allocates a new window (tagWND) on the user heap using win32k!HmAllocObject. This returns a handle integer into the global user handle table managed by win32k.

win32k!xxxCreateWindowEx then calls win32k!DwmAsyncChildCreate:

enter image description here

win32k!DwmAsyncChildCreate constructs a LPC _PORT_MESSAGE message and inserts the parameters of the call into the message. Object is the DWM ALPC port, a2 is the window handle hWND, a3 is the thread desktop window handle.

enter image description here

LPC is now implemented internally using ALPC, and can be synchronous or asynchronous, but in this case, the message is sent asynchronously.

dwm.exe has a port thread that waits on the port. The thread continually runs in CPortBase::PortThreadInternal, calling NtReplyWaitReceivePort on the ALPC port it created, and when it receives a message, it calls CPortBase::RoutePacket.

Several messages are sent to DWM, including when the window is shown or hidden.

Seeing as DWM has access to the hWND, it can get the device context (((PDCE)Wnd->pcls->pdce)->hDC), and then the surface from the _DC structure (DC->dclevel.pSurface). On a virtualbox win7 VM, it appears to be an engine managed surface because very few calls are made to cdd.dll, and on ShowWindowEx, win32k!hsurfCreateCompatibleSurface calls cdd!DrvCreateDeviceBitmapEx, which returns unimplemented, so then win32k!hsurfCreateCompatibleSurface instead calls win32k!SURFACE::bCreateDIB to create the surface. In this call, the surface object is inserted into GDI handle table (though it is at a kernel address, the kernel address range is mapped to different physical pages for each process) using HmgInsertObject. The handle HBITMAP appears to be a handle to the _BASEOBJECT of the SURFACE object, and the SURFACE object contains an embedded _SURFOBJ, which points to the first scan line of the bitmap via pvscan0. HSURF and HBITMAP appear to be the same.

The _DXGK_DRIVERCAPS structure returned by dxgkrnl!DxgkCddGetDriverCaps is the same as the one on VboxMPWddm.cpp on github, so clearly it is returning the _DXGK_DRIVERCAPS of the WDDM display miniport driver:

enter image description here

It can be seen that at offset 0x34, the _DXGK_PRESENTATIONCAPS contains 0x3, meaning SupportKernelModeCommandBuffer = 0 and therefore GDI is not accelerated.

It does appear to still pass some commands to dxgkrnl which then gets sent to the WDDM miniport, such as changing the pointer shape:

enter image description here

I'm not sure what happens when you have 2 screens and 2 display adapters and one supports GDI acceleration and the other doesn't.

I net debugged a windows 10 machine with an IGPU and something very different happened when creating a surface. This time cdd!DrvCreateDeviceBitmapEx creates a device surface:

enter image description here

dxgkrnl!DXGDEVICE::CreateStandardAllocation eventually results in calls to the display miniport driver.

The _DXGK_DRIVERCAPS this time is different, and SupportKernelModeCommandBuffer = 1 :

enter image description here

Whereas on the VM the surface is in system memory, the device surface (pointed to by pvscan0 of _SURFOBJ) is created in an aperture memory segment memory address accessible by the GPU. The surface is copied to VRAM and copied back again to the aperture memory. Whereas the CPU accesses the memory directly, the GPU accesses the system memory through the aperture.

cdd.dll appears to be a XPDM display miniport driver replacement for framebuf.dll that does not pass any of it to the XPDM GPU driver (video port, miniport pair; which used to be videoprt.sys, vgapnp.sys). Instead it passes some GDI stuff to the WDDM display miniport driver and the stuff that can't be accelerated to the GDI engine (the XPDM display driver).

DWM can then read this surface and can then convert it to a DirectX surface, composite, and then use the WDDM stack to display it to the screen.

I'm not sure about DirectX windows. I don't know much about DirectX workings, but I will update.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42