EngCreateDeviceSurface fails

I have a monolithic print driver built with the very latest DDK from MSDN.
The driver installs fine, and shows up in the lsit of asvailable printers.
When I print to it, all of the communications witrh the GDI are working good.

The problem happens when I try to switch from Engine Managed Surface to Device Managed Surface. I believe that I do not fully understand the difference between EngCreateBitmap and EngCreateDeviceSurface.

The surface of my device is fairly large (36" x 24") and resolve to a high dpi (5000 dpi.)
My device is also 24 bit color, so I need 24 bit surface bitmap.

The device surface is a raster AND a vector device.

36" x 5000 dpi = 180,000 pixels per scanline, x 3 (for 24 bit) = 540,000 bytes per scanline.

24" x 5000 dpi = 120,000 scanlines.

540,000 x 120,000 = 64,800,000,000 bytes
which is 60.349 GB

I have no intention of actually creating a bitmap that large. My goal is to “covince” the GDI that I have already created such a bitmap (perhaps in device memory) and that the GDI can therefore send all of the vectors fro a full contiguous page over at 5000 dpi.

I have no intentions of punting back to the GDI. I want to absorb the calls (all of which i have hooked) and take of writing to the device myself.

I notcies that the documentation for EngCreateDeviceSyrface says that I can “optimoally provide the surface memory” myself. I also note that after a call to EngCreateDeviceSurface that the returned surface contains pointer to pvBits, nor a delta, etc. This is good, because I intend to take care fo the rendering myself. it is my understanding that when I afterwards call EngModifySurface that I should still keep the GDI in the dark concering the pvBits and the Delta, etc.

The problem is that my call to EngCreateDeviceSurface fails, with an error code of zero.
My call looks like this…

SIZEL surfacedim;
surfacedim.cx = 180000;
surfacedim.cy = 120000;

mypdev->surface = EngCreateDeviceSurface((DHSURF)mpdev, surfacedim, BMF_24BPP);

I know I missing a point here somewhere… does EngCreateDeviceSurface actually TRY to allocate the 60 GB bitmap in this case, and thereby fails, or does EngCreateDeviceSurface NEVER try to allocate, and it is up to the driver to allocate and then use EngModifySurface to inform?

In the second case, I still have no intention of asking the OS to allocate the 60 GB bitmap. I merely need the GDI to believe that I have done som, so that the printing process can begin and I can start recieving all of the hooked DrvXXX calls for the full apge in fill color at a resolution of 5000 dpi.

So how am i failing to convince the GDI that I have the surface “taken care of”?

Cary Johnston

xxxxx@hotmail.com wrote:

I have a monolithic print driver built with the very latest DDK from MSDN.
The driver installs fine, and shows up in the lsit of asvailable printers.
When I print to it, all of the communications witrh the GDI are working good.

The problem happens when I try to switch from Engine Managed Surface to Device Managed Surface. I believe that I do not fully understand the difference between EngCreateBitmap and EngCreateDeviceSurface.

The surface of my device is fairly large (36" x 24") and resolve to a high dpi (5000 dpi.)
My device is also 24 bit color, so I need 24 bit surface bitmap.

Interesting. What’s the use case? The human eye can’t discern much
more than about 1000 dpi.

Your pixels are 1 square micron. What are you using to render dots of
that size? Certainly not ink, and there are darned few scribes that
could approach that.

The device surface is a raster AND a vector device.

36" x 5000 dpi = 180,000 pixels per scanline, x 3 (for 24 bit) = 540,000 bytes per scanline.

24" x 5000 dpi = 120,000 scanlines.

540,000 x 120,000 = 64,800,000,000 bytes
which is 60.349 GB

It would take 6 or 7 hours to transfer that via a high-speed USB pipe.
You have really piqued my interest here.

The problem is that my call to EngCreateDeviceSurface fails, with an error code of zero.
My call looks like this…

SIZEL surfacedim;
surfacedim.cx = 180000;
surfacedim.cy = 120000;

mypdev->surface = EngCreateDeviceSurface((DHSURF)mpdev, surfacedim, BMF_24BPP);

I know I missing a point here somewhere… does EngCreateDeviceSurface actually TRY to allocate the 60 GB bitmap in this case, and thereby fails, or does EngCreateDeviceSurface NEVER try to allocate, and it is up to the driver to allocate and then use EngModifySurface to inform?

At one point in time, there was a legacy issue that limited the number
of pixels in either direction to 32767. I had assumed that limitation
was gone, but perhaps that assumption is faulty. It’s certainly true
that the computation of the image size is going to overflow 4GB; perhaps
that’s enough to trigger this. I’m guessing you’ll have to single step
into EngCreateDeviceSurface to figure out what it doesn’t like.


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

Tim Roberts wrote:

xxxxx@hotmail.com wrote:

> The surface of my device is fairly large (36" x 24") and resolve to a high dpi (5000 dpi.)
> My device is also 24 bit color, so I need 24 bit surface bitmap.
>

Interesting. What’s the use case? The human eye can’t discern much
more than about 1000 dpi.

Your pixels are 1 square micron.

Whoops, make that 10 microns square. Order of magnitude problem.


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

> At one point in time, there was a legacy issue that limited

the number of pixels in either direction to 32767. I had
assumed that limitation was gone, but perhaps that assumption
is faulty. It’s certainly true that the computation of the
image size is going to overflow 4GB; perhaps that’s enough to
trigger this. I’m guessing you’ll have to single step into
EngCreateDeviceSurface to figure out what it doesn’t like.

I regularly create a device surface 36" x 100’ x 600 DPI, which is >
15GB I believe.

I believe (some) applications may still have an issue with 32767.

ScottR

>Interesting. What’s the use case? The human eye can’t discern much

more than about 1000 dpi.

The device is a motion controlled Co2 laser engraver with a table size of 36" x 24".
The Y axis has a stepper motor which moves in increments of 0.000197", or 5076 dpi
The X axis has a stepper motor which moves in increments of 0.000236", or 4237 dpi
I merely rounded to 5000 for both to make describing the problem easier.

Your pixels are 1 square micron. What are you using to render dots of
that size? Certainly not ink, and there are darned few scribes that
could approach that.

it is true that, even though the mechanical motor resolution of the device is roughly 5000 dpi, the limiting factor is the how small, or tightly focused, we can get the laser spot. Theoretically the tightest spot size we can get at the moment is about 0.0015", which is about 667 dpi. On some other materials, like wood, so much of the wood immediately around the focused spot size ignites and burns that you can end up with a spot size of .012", or 83 dpi.

The laser is capable of doing raster style engraving (like bitmaps), as well as free drawn vectors.
The jobs going to the laser can be hybrind jobs which contain both raster and vector.

The goal is to render the raster bitmaps and vectors at seapate resolutions. For example, a user might build a hybrimd job that contains raster images which need to go out at 200 dpi, but also contains vectors which need to be drawn at the highest machine resolution possible, 5000 dpi.
More detail below.

It would take 6 or 7 hours to transfer that via a high-speed USB pipe.
You have really piqued my interest here.

Correct, but there is no intention of actually allocating a 60 GB bitmap and therfroe no need to transfer it. The goal is to “covnince” the GDI that the driver has taken care of allocating the bitmap, so that the high resolution surface can then be EngAssociated with the device with all of the appropriate hooks.

At one point in time, there was a legacy issue that limited the number
of pixels in either direction to 32767. I had assumed that limitation
was gone, but perhaps that assumption is faulty.

I think your assumption about that being fixed is correct. If instead of a 36" x 24" 5000 dpi surface, I ask for a 8.5" x 11" 5000 dpi surface, the EngCreateDeviceSurface call succeeds. Upon inspection of the returned SURFOBJ (via EngLockSurface) the sizlBitmap.cx = 42500 and cy = 55000, so 32767 is no longer a limiting factor.

It’s certainly true
that the computation of the image size is going to overflow 4GB; perhaps
that’s enough to trigger this.

Upon inspection of the “smaller” surface (above example) the cvBits is indeed “overflowed” as you predict. But the surface still works in calls to the GDI. Also, the lDelta = 0 and the pvBits = NULL, which makes me think that no memory was allocated for the smaller surface. The above example smalelr surface would be 42500 x 3 x 55000 = 6.53 GB.

The interesting thing is that my devlopment box has 64 bit windows 7 with 8 gigs of RAM, so it is “almost” like EngCreateDeviceSurface is checking to see how much RAM the sytem has, EVEN though it isn’t goign to actually allocate any memory.

So in a nutshell, on my 8 GB devlopment system, I make a call to EngCreateDeviceSurface with a size of 42000 x 55000 BMF_24BPP, (which would be 6.5 GB, less than my available RAM) and the call succeeds and returns a surface.

But when I then change the szie to 36" x 24", and make the same call with a size of 180000 x 120000 BMF_24BPP (which would be 60 GB, waay past my RAM limit) the call fails.

What I don;t understand is, if EngCreateDeviceSurface does not allocate memory, why does it matter? SInce the 32767 limit is no longer concern (as shown by a successful return using 42500 x 55000), then 18000 x 120000 are also safely under the radar.

in essence what I am tryign to do is this:

Create an “official” surface at 36" x 24" 5000 dpi (which I have no intention of using).
Assocaite that surface via EngAssociateSurface, and hook ALL of the functions

Capture all output, at 5000 dpi,

So for calls to “vector” functions like DrvStrokePath, etc, cache the vector points out to the device,
no bitmap needed, no punitng to the GDI.

For “raster” functions like DrvStretchBlt, etc, cache the source bitmap and use my own routines to output to the device, and still no punting to the GDI.

I need to convince that I have the 5000 dpi surface (for the full surface, NOT banded) handled, so that it will proceed to send the calls my way.

Tim Roberts wrote:

> 540,000 x 120,000 = 64,800,000,000 bytes
> which is 60.349 GB

It would take 6 or 7 hours to transfer that via a high-speed
USB pipe. You have really piqued my interest here.

Glug glug?

>>> 540,000 x 120,000 = 64,800,000,000 bytes

>> which is 60.349 GB
>
> It would take 6 or 7 hours to transfer that via a high-speed
> USB pipe. You have really piqued my interest here.

Glug glug?

30MB/s is achievable in USB high-speed, so, ~2000s which is < 1 hour, more like 40 minutes.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

PCIe X16 is 80 Gb/sec, so 60 GB * 8 = 480 Gbits => about 6 or 7 seconds…

xxxxx@gmail.com wrote:

From: xxxxx@gmail.com
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] EngCreateDeviceSurface fails
Date: Mon, 3 May 2010 17:13:15 -0400 (EDT)

Tim Roberts wrote:

>> 540,000 x 120,000 = 64,800,000,000 bytes
>> which is 60.349 GB
>
> It would take 6 or 7 hours to transfer that via a high-speed
> USB pipe. You have really piqued my interest here.

Glug glug?


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

“Gregory G Dyess” wrote in message news:xxxxx@ntdev…
> PCIe X16 is 80 Gb/sec, so 60 GB * 8 = 480 Gbits => about 6 or 7 seconds…

It is 80 GB/sec in both directions. One way only (2.5*16) gives 40.
– pa

> From: xxxxx@gmail.com
> To: “Windows System Software Devs Interest List”
> Subject: RE:[ntdev] EngCreateDeviceSurface fails
> Date: Mon, 3 May 2010 17:13:15 -0400 (EDT)
>
> Tim Roberts wrote:
>
>>> 540,000 x 120,000 = 64,800,000,000 bytes
>>> which is 60.349 GB
>>
>> It would take 6 or 7 hours to transfer that via a high-speed
>> USB pipe. You have really piqued my interest here.
>
> Glug glug?
>
> —
> 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 2b out of 10 are not used to carry “messages”, like any TBI serdes.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel A.
Sent: Monday, May 03, 2010 5:49 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] RE:EngCreateDeviceSurface fails

“Gregory G Dyess” wrote in message news:xxxxx@ntdev…
> PCIe X16 is 80 Gb/sec, so 60 GB * 8 = 480 Gbits => about 6 or 7 seconds…

It is 80 GB/sec in both directions. One way only (2.5*16) gives 40.
– pa

> From: xxxxx@gmail.com
> To: “Windows System Software Devs Interest List”
> Subject: RE:[ntdev] EngCreateDeviceSurface fails
> Date: Mon, 3 May 2010 17:13:15 -0400 (EDT)
>
> Tim Roberts wrote:
>
>>> 540,000 x 120,000 = 64,800,000,000 bytes
>>> which is 60.349 GB
>>
>> It would take 6 or 7 hours to transfer that via a high-speed
>> USB pipe. You have really piqued my interest here.
>
> Glug glug?
>
> —
> 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

>I regularly create a device surface 36" x 100’ x 600 DPI, which is >

15GB I believe.

Scott, yes, a BMF_8BPP surface 36" x 1200" x 600 dpi would be right under 15 GB.

how are you making the call? are you using EngCreateDeviceSurface like this…

SIZEL surface;
surface.cx = 21600;
surface.cy = 720000;

something = EngCreateDeviceSurface((DHSURF)??, surface, BMF_8BPP);

Does your development box have 15 GB of RAM?

If not, I am curious to find out how your call is succeeding.

> how are you making the call? are you using

EngCreateDeviceSurface like this…

SIZEL surface;
surface.cx = 21600;
surface.cy = 720000;

something = EngCreateDeviceSurface((DHSURF)??, surface, BMF_8BPP);

Does your development box have 15 GB of RAM?

No, my development machine has 4GB of RAM.

My surface is 24BPP, I may have done the calculation wrong before.

Yes, that is pretty much how I call EngCreateDeviceSurface. I don’t use
??, I use the parameter passed in to DrvEnableSurface. Which, if my
comments are correct, is the value I returned earlier from
DrvEnablePDEV.

DrvEnablePDEV fills in a DEVINFO structure which also contains the
surface size. Perhaps your DrvEnablePDEV is filling in a different
value? I don’t know if that is the problem, I’ve never done that so I
can’t say. But it might be something to look at. There might be
something else there to look at as well.

ScottR

Calvin Guan wrote:

And 2b out of 10 are not used to carry “messages”, like any TBI serdes.

Yes; we found that somewhere around 55-60% of a PCIe’s link bandwidth
was really available for data.


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

Looks like I am going to have to fall back on Tim’s suggestion of tracing into the EngCreateDeviceSurfacve call to see exactly what circumstance causes it to fail.

i have never done so…I assume the best way is to find a spare box, install a checked build of the OS with all the appropriate symbol sets, and then i should be able to step into EngCreateDeviceSurface.

I am curious why Scott’s call works and mine doesn’t…

Scott’s = 36" x 1200" x 600 dpi x BMF_24BPP = 43.45 GB
his box has 4 GB of RAM, and the call succeeds.

Mine = 36" (4723 dpi) x 24" (5076 dpi) x BMF_24BPP = 51.92 GB
my box has 8 GB of RAM, and the call fails.

I can’t get he call to succeed until I drop down to
36" (1412 dpi) x 24" (1692 dpi) x BMF_24BPP = 5.77 GB
at which point you can see I am finally under the 8 GB RAM on my box.

I wonder if non-square dpi has anything to do with it?
My Driver version had been set to DDI_DRIVER_VERSION_NT4
I changed that to DDI_DRIVER_VERSION_NT5_01_SP1
and it still made no difference.

I am building using the Windows 7 x64 Checked build environment.

Per Scott’s suggestion I double checked to make sure my GDIINFO structure is set to 4237 xdpi x 5076 y dpi, 36" x 24" to make sure everything matches.

Perhaps a DEVINFO flag is conflicting? like GCAPS_ALTERNATEFILL, etc.
Could there possibly be something in the INF installer file which is conflicting?

Also, I am telling GDIINFO that the technology is DT_RASTPRINTER.
Doesn anyone know what actually happens, GDI wise, as a result of changing that flg to DT_PLOTTER?

xxxxx@hotmail.com wrote:

Looks like I am going to have to fall back on Tim’s suggestion of tracing into the EngCreateDeviceSurfacve call to see exactly what circumstance causes it to fail.

i have never done so…I assume the best way is to find a spare box, install a checked build of the OS with all the appropriate symbol sets, and then i should be able to step into EngCreateDeviceSurface.

You don’t actually need a checked build of the OS. You can start from
breakpoints in your own code and single-step into
EngCreateDeviceSurface. You’ll need to have a grasp of x64 assembler,
but since you’re just looking for an error return, you should be able to
narrow it down pretty quickly.

I am curious why Scott’s call works and mine doesn’t…

Me, too.

I wonder if non-square dpi has anything to do with it?

No, that’s always been supported. The EGA had non-square pixels. Lots
of printers are 600 dpi in one direction and 1200 dpi in the other.


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

As an experiment, I added:
sizlDev.cx = 1800000; // your values *10
sizlDev.cy = 1200000;
ERRORMSG(_T(“sizlDev passed to CreateDeviceSurface is (%d,%d)”),
sizlDev.cx, sizlDev.cy);
// Call the engine to create a surface handle for us.
pd->m_hSurface = EngCreateDeviceSurface((DHSURF)pd, sizlDev,
BMF_24BPP);

to my DrvEnableSurface and the call to EngCreateDeviceSurface didn’t
fail.

Have you called GetLastError() to see if it has anything to say?

ScottR

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Tuesday, May 04, 2010 2:27 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] EngCreateDeviceSurface fails

Looks like I am going to have to fall back on Tim’s
suggestion of tracing into the EngCreateDeviceSurfacve call
to see exactly what circumstance causes it to fail.

i have never done so…I assume the best way is to find a
spare box, install a checked build of the OS with all the
appropriate symbol sets, and then i should be able to step
into EngCreateDeviceSurface.

I am curious why Scott’s call works and mine doesn’t…

Scott’s = 36" x 1200" x 600 dpi x BMF_24BPP = 43.45 GB his
box has 4 GB of RAM, and the call succeeds.

Mine = 36" (4723 dpi) x 24" (5076 dpi) x BMF_24BPP = 51.92 GB
my box has 8 GB of RAM, and the call fails.

I can’t get he call to succeed until I drop down to 36" (1412
dpi) x 24" (1692 dpi) x BMF_24BPP = 5.77 GB at which point
you can see I am finally under the 8 GB RAM on my box.

I wonder if non-square dpi has anything to do with it?
My Driver version had been set to DDI_DRIVER_VERSION_NT4 I
changed that to DDI_DRIVER_VERSION_NT5_01_SP1 and it still
made no difference.

I am building using the Windows 7 x64 Checked build environment.

Per Scott’s suggestion I double checked to make sure my
GDIINFO structure is set to 4237 xdpi x 5076 y dpi, 36" x 24"
to make sure everything matches.

Perhaps a DEVINFO flag is conflicting? like GCAPS_ALTERNATEFILL, etc.
Could there possibly be something in the INF installer file
which is conflicting?

Also, I am telling GDIINFO that the technology is DT_RASTPRINTER.
Doesn anyone know what actually happens, GDI wise, as a
result of changing that flg to DT_PLOTTER?


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

Scott, Wow, that is a 5.89 terabyte surface!
(by the way, did you adjust your GDIINFO size info to match?)
Thanks for doing that experiment. I am sure now that I must have something somewhere set wrong, as the call obviously is not tied to system RAM in any way.

Have you called GetLastError() to see if it has anything to say?

I did put in a call to GetLastError() and it returned 0.

I am going to go back and make sure that I idn’t hit any other API calls after EngCreateDeviceSurface which would have destroyed any valid error return from GetLastError().

I did adjust the gdiinfo structure, but it was a quick hack, I may have
gotten some numbers wrong.

ScottR

Tim, Scott,

I have been slicing at this the last few days, and I have discovered some interesting peculiarities.

First, I took a close look at the surface sizes that were failing…

cx = 152,543 cy = 121,827 FAIL!
cx = 76,271 cy = 60,913 FAIL!
cx = 50,847 cy = 40,609 SUCCEED

As originally posted in this thread I had noticed that …
50847 x 40609 x BMF_24BPP = 5.76 GB, which was under 8 GB RAM on my box.
The other failed values were greater than 8 GB, so I surmised that somehow EngCreateDeviceSurface was checking my available RAM.

I built a x86 version of the driver and installed on a box with 2 GB of RAM, expecting
to not get a successful surface until I dropped below 2 GB. However, the 2 GB box still successfully created the 50847 x 40609 surface at 5.76 GB.

After looking closer, I noticed that both numbers, 50847 and 40609, were UNDER 65535.
So thinking I might have an overflow problem, I built the following test loop into my DrvEnableSurface function…

SIZEL surface;
BOOL floppy = TRUE;

surface.cx = 65540;
surface.cy = 65540;

while (mypdev->hsurf = EngCreateDeviceSurface((DHSURF)mypdev, surface, BMF_24BPP) == NULL)
{
if (floppy == TRUE)
surface.cx --;
else
surface.cy --;

floppy = !floppy;
}

here was the result of that pass…

cx = 65540 cy = 65540 FAIL!
cx = 65539 cy = 65540 FAIL!
cx = 65539 cy = 65539 FAIL!
cx = 65538 cy = 65539 FAIL!
cx = 65538 cy = 65538 FAIL!
cx = 65537 cy = 65538 FAIL!
cx = 65537 cy = 65537 FAIL!
cx = 65536 cy = 65537 FAIL!
cx = 65536 cy = 65536 FAIl!
cx = 65535 cy = 65536 SUCCESS

I was intrigued by the fact that cy did not need to drop below 65536, so I kept the same loop but started “floppy” out a FALSE so that cy would be decremented first. This is what that pass brought…

cx = 65540 cy = 65540 FAIL!


cx = 65537 cy = 65536 FAIL!
cx = 65536 cy = 65536 FAIL!
cx = 65536 cy = 65535 SUCCESS

This seemed to indicate that, for some reason, the “sum” of both numbers could not
overflow 65536 x 65536. So I took an arbitrary value, 150,000, and chose the other number like this…

4,294,967,296 / 150,000 = 28,633.11531

so now I changed my loop as follows…

surface.cx = 150000;
surface.cy = 28640;

while (mypdev->hsurf = EngCreateDeviceSurface((DHSURF)mypdev, surface, BMF_24BPP) == NULL)
{
surface.cy --;
}

Here is the result of that pass…

cx = 150000 in all cases…

cy = 28640 FAIL!
cy = 28639 FAIL!
cy = 28638 FAIL!
cy = 28637 FAIL!
cy = 28636 FAIL!
cy = 28635 FAIL!
cy = 28634 FAIL!
cy = 28633 SUCCESS

This is interesting, the math on that comes out to this…

150,000 x 28633 x BMF_24BPP = 12 GB

and that is definitely over my RAM limit on my box.

So the evidence seems to be that the problem is not tied to RAM limit, but a strange overflow.
And the thing is, the overflow is NOT the cvBits member of SURFOBJ, because that overflows on the above example, and the surface is still created.

The overflow seems to be tied to the value of the pixel width x pixel height, without any regard to number of bits perpixel.

I cannot find anywhere in the GDIINFO, DEVINFO, DEVMODEW, etc, structures, where we pass in such a value.

This seems to be something happening within the guts of GDI.

Does this ring a bell for any of you guys? is it possible that something in my SOURCES files, my INF file, or my build environment, or compiler settings, etc, is causing this strange behaviour?

This is a user mode print driver, targetting Win XP service pack 1 and higher.
Same behaviour in both amd64 and x86 builds.

I think it’s clearly not memory related, you need to look elsewhere.

My driver actually doesn’t look at the surface’s size anywhere else
other than when it creates it, because it knows the size (my dhpdev
includes a devmode). So technically I think I could create the surface
as (0,0). I think the size would only be needed if you ever do a
EngModifySurface.

You are using the WDK build environment and not visual studio for
building, right?

ScottR

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Friday, May 07, 2010 12:57 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] EngCreateDeviceSurface fails

Tim, Scott,

I have been slicing at this the last few days, and I have
discovered some interesting peculiarities.

First, I took a close look at the surface sizes that were failing…

cx = 152,543 cy = 121,827 FAIL!
cx = 76,271 cy = 60,913 FAIL!
cx = 50,847 cy = 40,609 SUCCEED

As originally posted in this thread I had noticed that …
50847 x 40609 x BMF_24BPP = 5.76 GB, which was under 8 GB RAM
on my box.
The other failed values were greater than 8 GB, so I surmised
that somehow EngCreateDeviceSurface was checking my available RAM.

I built a x86 version of the driver and installed on a box
with 2 GB of RAM, expecting to not get a successful surface
until I dropped below 2 GB. However, the 2 GB box still
successfully created the 50847 x 40609 surface at 5.76 GB.

After looking closer, I noticed that both numbers, 50847 and
40609, were UNDER 65535.
So thinking I might have an overflow problem, I built the
following test loop into my DrvEnableSurface function…

SIZEL surface;
BOOL floppy = TRUE;

surface.cx = 65540;
surface.cy = 65540;

while (mypdev->hsurf = EngCreateDeviceSurface((DHSURF)mypdev,
surface, BMF_24BPP) == NULL) {
if (floppy == TRUE)
surface.cx --;
else
surface.cy --;

floppy = !floppy;
}

here was the result of that pass…

cx = 65540 cy = 65540 FAIL!
cx = 65539 cy = 65540 FAIL!
cx = 65539 cy = 65539 FAIL!
cx = 65538 cy = 65539 FAIL!
cx = 65538 cy = 65538 FAIL!
cx = 65537 cy = 65538 FAIL!
cx = 65537 cy = 65537 FAIL!
cx = 65536 cy = 65537 FAIL!
cx = 65536 cy = 65536 FAIl!
cx = 65535 cy = 65536 SUCCESS

I was intrigued by the fact that cy did not need to drop
below 65536, so I kept the same loop but started “floppy” out
a FALSE so that cy would be decremented first. This is what
that pass brought…

cx = 65540 cy = 65540 FAIL!


cx = 65537 cy = 65536 FAIL!
cx = 65536 cy = 65536 FAIL!
cx = 65536 cy = 65535 SUCCESS

This seemed to indicate that, for some reason, the “sum” of
both numbers could not overflow 65536 x 65536. So I took an
arbitrary value, 150,000, and chose the other number like this…

4,294,967,296 / 150,000 = 28,633.11531

so now I changed my loop as follows…

surface.cx = 150000;
surface.cy = 28640;

while (mypdev->hsurf = EngCreateDeviceSurface((DHSURF)mypdev,
surface, BMF_24BPP) == NULL) {
surface.cy --;
}

Here is the result of that pass…

cx = 150000 in all cases…

cy = 28640 FAIL!
cy = 28639 FAIL!
cy = 28638 FAIL!
cy = 28637 FAIL!
cy = 28636 FAIL!
cy = 28635 FAIL!
cy = 28634 FAIL!
cy = 28633 SUCCESS

This is interesting, the math on that comes out to this…

150,000 x 28633 x BMF_24BPP = 12 GB

and that is definitely over my RAM limit on my box.

So the evidence seems to be that the problem is not tied to
RAM limit, but a strange overflow.
And the thing is, the overflow is NOT the cvBits member of
SURFOBJ, because that overflows on the above example, and the
surface is still created.

The overflow seems to be tied to the value of the pixel width
x pixel height, without any regard to number of bits perpixel.

I cannot find anywhere in the GDIINFO, DEVINFO, DEVMODEW,
etc, structures, where we pass in such a value.

This seems to be something happening within the guts of GDI.

Does this ring a bell for any of you guys? is it possible
that something in my SOURCES files, my INF file, or my build
environment, or compiler settings, etc, is causing this
strange behaviour?

This is a user mode print driver, targetting Win XP service
pack 1 and higher.
Same behaviour in both amd64 and x86 builds.


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