Prev: Running Windows XP and Windows Vista Professional in headless mode
Next: Virtual Audio Device Driver Question
From: blackborn on 16 Mar 2007 12:26 I'm developing a mirror display driver, that punts all ddi calls (maked to the associated device surface) to the gdi-managed surface, created with the EngCreateBitmap. All works fine, except DrvAlphaBlend- >EngAlphaBlend. EngAlphaBlend crashes in the win32k.sys (xp sp2) when called for the gdi-managed surface, but for the device-managed surface it works fine (breaks down blend to lower blt operations). When i use the gdi-managed bitmap as associated surface, it is also works fine. All parameters for punted call to EngAlphaBlend are correct (i only replace device-managed surfaces (src or\and dest) to gdi-maneged). Maybe, i missed some important concept or there is more correct and simple way to punt all mirrored calls to the gdi-managed surface (i need also track all calls\changes)? Thanks!
From: blackborn on 16 Mar 2007 14:44 Ivan, thanks for answer! > You can call EngXXX only with Eng-Managed bitmaps. But DDK says: A bit-block transfer with alpha blending is supported between the following surfaces: >From one device-managed surface to another device-managed surface. >From one GDI-managed standard format bitmap to another GDI-managed standard format bitmap. >From one device-managed surface to a GDI-managed surface, and vice versa. == And in practice this works (expands to lower calls - textout, blt, copy etc) - except AlphaBlend with DIB-DIB. But strange - when DIB associated with device (aka primary surface) - all works fine. But for Eng-Managed bitmap it fails.. only AlphaBlend, other EngXxx works. > Maybe you are bing called with a device-owned *SOURCE* > and an Eng-Managed *DESTINATION*, and, you are missing this case > when you craft an Eng-Manager SURFOBJ before calling EngXXX No. I surely handle such case: if (psoDst) { if (psoDst->dhsurf) { 1. // bReturn = EngAlphaBlend(pDevice->m_pBackSurf, ((psoSrc) && (psoSrc->dhsurf)) ? pDevice->m_pBackSurf : psoSrc, pco, pxlo, prclDest, prclSrc, pBlendObj); 2. // bReturn = EngAlphaBlend(psoDst, psoSrc, pco, pxlo, prclDest, prclSrc, pBlendObj); 1. - fails 2. - works (expands to lower blt calls). all others cases silently returns true without putning. I think we should not copy from a device to eng managed surfaces in mirror drivers? or we must punt all calls? Ultravnc punts only if dest is device managed, but it uses DIB as primary surface (strange, that it calls EngXxx ever - just can return FALSE from DrvXxx for auto punt?). As i mentioned before, it works and in my case. But i have a device- managed surface as primary (i create eng managed mirror surface only when it is really needed)... -- Andrew Solodovnikov
From: blackborn on 16 Mar 2007 19:13 > I guess the DDK is speaking from the caller point of view, > while I was thinking of the code that detects a punted call > and breaks that down to DrvCopyBits/EngXXX/DrvCopyBits. Hmm. But why others punted EngXxx works as expected? And also i find your messages about it: http://groups.google.com/group/comp.os.ms-windows.programmer.nt.kernel-mode/browse_frm/thread/405afc6193af138c/e5bb277f48f93a6c As i understand, you had spoke definitely about same things - the primare device managed surface and the "mirror" eng-managed: == This way win32k.sys will call the Driver for the callbacks specified in the EngCreateDeviceSurface, and, in each of the implemented DrvXXX functions, you can punt-to-Eng using the STYPE_BITMAP SURFOBJ. == I done the same thing - create the primary surface with the EngCreateDeviceSurface, EngAssociateSurface and then in the ExtEscape create the mirror surface with the EngCreateBitmap. > The code below works under a few assumptions: > - the driver does not have device-compatible surfaces > - the primary surface is an Eng-Managed surface > Maybe UltraVNC satisfies those assumptions. But if the primary surface is Eng-managed and we not hook _all_ DrvXxx (that can draw on surface), then gdi may draw on it without notifications? This unacceptable (for example, coz it will not work on a newer ddi engines, and i wonder about vnc mirror driver - it's surely not correct, coz it hooks not all of the appropriate DrvXxx). > > Can you post the stack of the crash that > you can get from a kernel-debugger session ? Yes, surely: f82783d8 bf9e8c7e e1acba48 e1a954d0 e1494d58 win32k!EngAlphaBlend +0x1a9 WARNING: Stack unwind information not available. Following frames may be wrong. f8278450 bf84d747 e10c46c8 e1a601b0 e1494d58 Rcphook+0xc7e f82784a0 bf95b074 bf9e8c0e e10cce70 e10c46c8 win32k!OffAlphaBlend+0x91 f82785f0 bf83a18e e10c4920 e1a601b0 f8278620 win32k!MulAlphaBlend +0x382 f82787ec 804df06b 01010054 00000000 e10a9e88 win32k!NtGdiAlphaBlend +0xb55 f82787ec 7c90eb94 01010054 00000000 e10a9e88 nt!KiFastCallEntry+0xf8 00e8f44c 00000000 00000000 00000000 00000000 0x7c90eb94 f8278ad8 80566730 f8278b94 f8278b98 f8278b68 nt!KiCallUserMode+0x4 f8278b34 bf813d09 00000002 f8278b78 00000018 nt!KeUserModeCallback +0x87 f8278bb8 bf813ea0 bc636c90 00000128 00010001 win32k!SfnDWORD+0xa8 f8278c00 bf814092 02636c90 00000128 00010001 win32k! xxxSendMessageToClient+0x176 f8278c4c bf80f470 bc636c90 00000128 00010001 win32k! xxxSendMessageTimeout+0x1a6 f8278c70 bf809b52 bc636c90 00000128 00010001 win32k!xxxSendMessage +0x1b f8278cd4 bf80f436 bc636ba8 00000128 00010001 win32k! xxxRealDefWindowProc+0xe3a f8278cec bf81bca1 bc636ba8 00000128 00010001 win32k! xxxWrapRealDefWindowProc+0x16 f8278d08 bf80f67d bc636ba8 00000128 00010001 win32k!NtUserfnDWORD+0x27 f8278d40 804df06b 0003003c 00000128 00010001 win32k!NtUserMessageCall +0xae f8278d40 7c90eb94 0003003c 00000128 00010001 nt!KiFastCallEntry+0xf8 00e8fb14 00000000 00000000 00000000 00000000 0x7c90eb94 f8278450 bf84d747 Rcphook+0xc7e - exactly after the EngAlphaBlend in the previously posted code. Code from the point of the crash: bf9037d0 5e pop esi bf9037d1 5b pop ebx bf9037d2 c9 leave bf9037d3 c21c00 ret 0x1c bf9037d6 8b431c mov eax,[ebx+0x1c] >>bf9037d9 8b8008030000 mov eax,[eax+0x308] ds:0023:00000308=???????? bf9037df 894518 mov [ebp+0x18],eax bf9037e2 e967feffff jmp win32k!EngAlphaBlend+0x1b2 (bf90364e) bf9037e7 8b4508 mov eax,[ebp+0x8] bf9037ea f6404904 test byte ptr [eax+0x49],0x4 bf9037ee 8955d4 mov [ebp-0x2c],edx bf9037f1 8955d8 mov [ebp-0x28],edx bf9037f4 742a jz win32k!EngAlphaBlend+0x35b (bf903820) bf9037f6 8b481c mov ecx,[eax+0x1c] bf9037f9 8b89e4050000 mov ecx,[ecx+0x5e4] Thanks! == Andrew Solodovnikov
From: blackborn on 17 Mar 2007 20:23 > My points about punting are the following: > -1- If you know you are going to punt a call, > do not report the capability in the Hook-Flags bassed to EngCreateSurface. No, i need to be notified about ddi calls. So i must hook all calls - in highest possible level, or expanded to the lower (DrvCopyBits, for example). As i understand, there is only way to achieve this - by creating a device managed surface and associate it as primary, but punting calls to an another, eng-managed surface. > -2- If you really want to punt, please translate the SURFOBJ to something > that Eng can scribble on. And i done it - all punts to the surface, created with EngCreateBitmap. > -3- If you punt without translating the SURFOBJ, then, Eng will make > a best effor to detect a puntend call, and, > it will implement again the CopyBits/EngXXX/CopyBits stuff. > This works fine for EngAlphaBlend, as i mentioned before... > Eng MUST be able to scribble the pixel (for read and write, dipending > on the Operation, the ROP, etc, etc). > For an opaque surface, the only method to read and write the pixels > is to copy them somewhere. > If you don't want a copy, create a STYPE_BITMAP surfobj with a > driver supplied frame buffer. > > But if the primary surface is Eng-managed and we not hook _all_ DrvXxx > > (that can draw on surface), then gdi may draw on it without > > notifications? > > The only notification you will have in this case are two DrvCopyBits calls. > In fact, if you set the Acceleration level to the lowest, that is what will > happen anyway. It is not clear for me. For example, my primary surface is STYPE_BITMAP. I want to hook CopyBts, BitBlt, TextOut and set appropriate flags in call to EngAssociateSurface. What will happens, when my driver receive, for example, AlphaBlend? As i know, in a callback table, that gdi builds for driver, it place EngAlphaBlend in INDEX_DrvAlphaBlend entry. So it just calls EngAlphaBlend and modifies surface silently without notifying my driver. Is this correct? > > For your crash, > > From the disassembly, it looks like the SURFOBJ::hdev is NULL for the > source, > and, there is no XLATEOBJ Hmm. I surely punt it to the EngAlphaBlend. I think, the SURFOBJ with null hdev is the pDevice->m_pBackSurf, coz it is not associated with the driver. Lets ressemle the simplified order of operations: 1. DrvEnableSurface 1.1. prim_surf = EngCreateDeviceSurface; 1.2. mirr_surf = EngCreateBitmap; 1.3. EngAssociateSurface(prim_surf); 2. DrvAlphaBlend 2.1. replace prim_surf with mirr_surf, when needed; 2.2. punt call, when needed. > > 0:000> u bf8be95d > win32k!EngAlphaBlend+0x196 [d:\nt\windows\core\ntgdi\gre\alphablt.cxx @ > 1470]: > bf8be95d 8b411c mov eax,dword ptr [ecx+1Ch] // SURFOBJ::hdev > bf8be960 8b8008030000 mov eax,dword ptr [eax+308h] > bf8be966 89450c mov dword ptr [ebp+0Ch],eax > > Can you `dt SURFOBJ <address_surfobj_src>` ? > > I'd be curious to see where that soruce SURFOBJ comes from, > but, without your code, it's not easy. Maybe... Can i modify the sample mirror driver from the DDK to reproduce this crash and post\send a result code to you?
From: blackborn on 18 Mar 2007 11:48 > > What will happens, when my driver receive, for example, AlphaBlend? As > > i know, in a callback table, that gdi builds for driver, it place > > EngAlphaBlend in INDEX_DrvAlphaBlend entry. So it just calls > > EngAlphaBlend and modifies surface silently without notifying my > > driver. Is this correct? > > Not completely. > the PDEV for your display driver will contain empty > entries for the non implemented DrvXXX calls. > If there is no entry, the system will call EngXXX. In the Feng Yuan's book there is a sample with internal "final" DDI function table for display driver. Commented, that in place of callbacks, not supported by driver, gdi will insert EngXxx function to that table, so calls goes directly to that function. From the "user" side it looks exactly as you said. > EngXXX will take care from this point on. > It will call DrvCopyBits to read the surface > (if the operation requires a read), or, > it will implement the operation > and the it will call CopyBits with the final result. > > Something like: > EngXXX(pDestination, pSource) > { > SURFOBJ pDibSource; > if (!eng_managed(pSource)) { > pDibSource = CreateDIBforSource(); > CopyBits(pDibSource,pSource); > } else { > pDibSource = pSource; > } > SURFOBJ pDibDest; > if (!eng_managed(pDest)) { > pDibDest = CreateDIBforSource(); > CopyBits(pDibDest,pDest); > } else { > pDibDest = pDestination; > } > > internalXXX(pDibDest,pDibSource); > > if (!eng_managed(pDest)) { > CopyBits(pDest,pDibDest); > } > > } > > Given that, not supporting an operation or punting will have the same > result: your driver will get a CopyBits with the final result. Hmm. Remember, that we talks about an eng-managed (STYPE_BITMAP) primary surface. From this code i see that a CopyBits will not be called at all. So if we not provide a DrvXxx operation (and have eng- managed primary surface), ddi will not inform us about that operation in any form - it just will silently draw directly to surface. Is this right? (It is not my case - this is how ultra vnc driver works. I just point, that we surely cannot use eng-managed primary surface, if we want to be informed about all operation on it. Right?) > > If you can repro on the DDK mirror driver, I will try to take a look. Thanks! I will post link to code tomorrow. > > BTW, supporting AlphaBlend is not a very interesting operation. > In the case of layered, redirected or composed windows, > it's better to have the final BitBlt from the pSoScreen kept by > the GDI sprite manager, instead of doing a chain or alphablend > for all the overlay and underaly of each layer in the Z-order. > At the end, you will receive what gets on the primary surface. Yes, but for windows XP i see some AlphaBlend calls without layered or composited windows. And i can effectively merge intersected calls - so it is not a big problem. > > One more thing, do you really have a primary surface that is STYPE_BITMAP ? I just talk about "ultra vnc style" mirror driver, that have STYPE_BITMAP primary surface :) I wonder about, why it works at all - it surely should loose some updates. There is one interesting thing - before associate eng-managed surface with a driver, they set hsurf member to non-null value (Lock\Set\Unlock). It is look like a some sort of "hack" to distinct the primary surface from other eng-managed surfaces... > That's an oximoron. You should have an STYPE_DEVICE that, possibly, > wraps a STYPE_BITMAP. I don't understand, really. How a STYPE_DEVICE can "wrap" a STYPE_BITMAP? Can you explain? If you talks about EngModifySurface - it can't be called with associated surfaces (after return from EngEnableSurface), as i know. Thanks! -- Andrew Solodovnikov
|
Next
|
Last
Pages: 1 2 Prev: Running Windows XP and Windows Vista Professional in headless mode Next: Virtual Audio Device Driver Question |