Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
When porting your code, consider the following points:
The following assumption is no longer valid:
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
However, the 64-bit compiler defines _WIN32 for backward compatibility.
The following assumption is no longer valid:
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
In this case, the else clause can represent _WIN32 or _WIN64.
Be careful with data-type alignment. The TYPE_ALIGNMENT macro returns the alignment requirements of a data type. For example:
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 on x86, 8 on Intel Itanium processorTYPE_ALIGNMENT( UCHAR )
== 1 everywhereAs an example, kernel code that currently looks like this:
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
should probably be changed to:
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Automatic fixes of kernel-mode alignment exceptions are disabled for Intel Itanium systems.
Be careful with NOT operations. Consider the following:
UINT_PTR a; ULONG b; a = a & ~(b - 1);
The problem is that ~(b–1) produces "0x0000 0000 xxxx xxxx" and not "0xFFFF FFFF xxxx xxxx". The compiler will not detect this. To fix this, change the code as follows:
a = a & ~((UINT_PTR)b - 1);
Be careful performing unsigned and signed operations. Consider the following:
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
The result is unexpectedly large. The rule is that if either operand is unsigned, the result is unsigned. In the preceding example, a is converted to an unsigned value, divided by b, and the result stored in c. The conversion involves no numeric manipulation.
As another example, consider the following:
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
The problem arises because x is unsigned, which makes the entire expression unsigned. This works fine unless y is negative. In this case, y is converted to an unsigned value, the expression is evaluated using 32-bit precision, scaled, and added to pVar1. A 32-bit unsigned negative number becomes a large 64-bit positive number, which gives the wrong result. To fix this problem, declare x as a signed value or explicitly typecast it to LONG in the expression.
Be careful when making piecemeal size allocations. For example:
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
The following code is wrong because the compiler will pad the structure with an additional 4 bytes to make the 8-byte alignment:
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
The following code is correct:
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Do not pass
(HANDLE)0xFFFFFFFF
to functions such as CreateFileMapping. Instead, use INVALID_HANDLE_VALUE.Use the proper format specifiers when printing a string. Use %p to print pointers in hexadecimal. This is the best choice for printing pointers. Microsoft Visual C++ supports %I to print polymorphic data. Visual C++ also supports %I64 to print values that are 64 bits.