jimtabor schrieb:
No, this would break compatibility. The way to verify
this. Write a
driver, install it
and send a packet to it, so to activate the test. Have the driver dump
to WinDbg.
Ok, I take my time to go into this, because I *am* interested in
compatibility.
Let's analyze how the conversion between FLOAT and EFLOAT works on XP.
We could simply use some documentation floating around, but let's do it
on our own, just for the fun. We don't need no
itchy-bitchy-kmtest-driver-callback-winpooch-hooky-thingy, because
Windows has already all we need to do this completely in user mode.
DC_ATTR has some EFLOATs and what we need is a function that takes a
FLOAT and stores it as EFLOAT. SetWorldTransform() seems suitable (In
fact the values will be stored in the DC_ATTR structure only after a
following call to GetWorldTransform()). And we need a windows compatible
structure definition for DC_ATTR, wich we can get from a well known
book. For the code see attachment.
Now let's see what we get with different parameters for the float:
f: 1.000000 (0x3f800000) -> lMant: 0x40000000, lExp: 0x000002
f: -1.000000 (0xbf800000) -> lMant: 0xc0000000, lExp: 0x000002
f: 2.000000 (0x40000000) -> lMant: 0x40000000, lExp: 0x000003
f: -2.000000 (0xc0000000) -> lMant: 0xc0000000, lExp: 0x000003
f: 1.500000 (0x3fc00000) -> lMant: 0x60000000, lExp: 0x000002
f: -1.500000 (0xbfc00000) -> lMant: 0xa0000000, lExp: 0x000002
f: 1235.000000 (0x449a6000) -> lMant: 0x4d300000, lExp: 0x00000c
f: -1235.000000 (0xc49a6000) -> lMant: 0xb2d00000, lExp: 0x00000c
Looks like Feng Yuan was right.
Now let's see what your code would do with f=1.
FtoEF( EFLOAT_S * efp, FLOATL f)
{
...
Exp = EXP(worker.l); // Exp = (((0x3f800000) >> 23L) & 0xFF) = 0x7F
Mant = MANT(worker.l); // Mant = ((0x3f800000) & 0x7FFFFFL) = 0x00000
Mant = ((Mant << 7) | 0x40000000 | SIGN(worker.l));
// Mant = (0 << 7) | 0x40000000 | (0x3f800000 & 0x80000000 )= 0 |
0x40000000 | 0 = 0x40000000
Exp -= (1 - EXCESS); // Exp = 0x7F - (1-126) = 0x7F + 0x7D = 0xFC
efp->lMant = Mant;
efp->lExp = Exp;
...
}
Replace the - by a + and you get
Exp += (1 - EXCESS); // Exp = 0x7F + (1-126L) = 0x7F - 0x7D = 0x2
Wich is what we have discovered windows does.
And it looks like there's another thing, you didn't take into account.
Ok, I give you a hint: It has something todo with the sign bit.
You don't get it? Well, it's all there!
Thanks,
Timo
typedef struct _GDI_TABLE_ENTRY
{
PVOID KernelData; /* Points to the kernel mode structure */
HANDLE ProcessId; /* process id that created the object, 0 for stock objects */
LONG Type; /* the first 16 bit is the object type including the stock obj flag,
the last 16 bits is just the object type */
PVOID UserData; /* Points to the user mode structure, usually NULL though */
} GDI_TABLE_ENTRY, *PGDI_TABLE_ENTRY;
typedef PGDI_TABLE_ENTRY (CALLBACK * GDIQUERYPROC) (void);
#define GDI_HANDLE_COUNT 0x10000
#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
#define GDI_HANDLE_GET_INDEX(h) \
(((ULONG_PTR)(h)) & GDI_HANDLE_INDEX_MASK)
typedef union
{
FLOAT f;
ULONG l;
} gxf_long;
typedef LONG FIX;
typedef struct _EFLOAT_S
{
LONG lMant;
LONG lExp;
} EFLOAT_S;
/* XFORM Structures */
typedef struct _MATRIX_S
{
EFLOAT_S efM11;
EFLOAT_S efM12;
EFLOAT_S efM21;
EFLOAT_S efM22;
EFLOAT_S efDx;
EFLOAT_S efDy;
FIX fxDx;
FIX fxDy;
FLONG flAccel;
} MATRIX_S;
/* Structure definition taken from Feng Yuan's book "Windows Graphics Programming
Win32 GDI and DirectDraw" */
typedef struct
{
void *pvLDC;
DWORD SomeStuff1[7];
#if _WIN32_WINNT >= 0x0500
DWORD SomeStuff2[4]; // 0x20
#endif
DWORD SomeStuff3[10]; // 0x030
#if _WIN32_WINNT >= 0x0500
DWORD SomeStuff4[8]; // 0x58
#endif
DWORD SomeStuff5[7]; // 0x78
MATRIX_S mxWorldToDevice; // 0x94
MATRIX_S mxDeviceToWorld; // 0xD0
MATRIX_S mxWorldToPage; // 0x10C
// More stuff we don't need
} DC_ATTR, *PDC_ATTR;