Delphi: add constant to TFileTime - delphi

I am new in Delphi and I need in my project add some constant to TFileTime which is record of lower and upper part of 64bit value. How to do this in Delphi? I have found only code in C++, but i dont know how make in Delphi unsigned int64 (ULONGLONG) and also I dont know how to cast this to longword (DWORD):
ULONGLONG qwResult;
// Copy the time into a quadword.
qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
// Add constant
qwResult += constant;
// Copy the result back into the FILETIME structure.
ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
Thanks

The FILETIME struct is defined as:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
So, because Windows runs on little Endian, the layout of this struct is compatible with a 64 bit integer value.
So, you can cast TFileTime to UInt64, do the arithmetic, and cast back. Like this:
function IncrementedFileTime(const Value: TFileTime; const Incr: UInt64): TFileTime;
begin
Result := TFileTime(UInt64(Value) + Incr);
end;
Now, the documentation for the FILETIME record says:
It is not recommended that you add and subtract values from the
FILETIME structure to obtain relative times. Instead, you should copy
the low- and high-order parts of the file time to a ULARGE_INTEGER
structure, perform 64-bit arithmetic on the QuadPart member, and copy
the LowPart and HighPart members into the FILETIME structure.
Do not cast a pointer to a FILETIME structure to either a
ULARGE_INTEGER* or __int64* value because it can cause alignment
faults on 64-bit Windows.
This is an issue on targets where alignment errors result in hard faults. For instance Itanium. However, on x86 and x64 the code in my answer is fine because those architectures do not issue hard faults for alignment errors. Which is just as well because the Delphi compiler isn't very good at alignment.

Related

Does the "low word" and "high word" locations of a WParam change in 64bit code?

I'm trying to handle the WM_XBUTTONUP message which is from the extra mouse buttons on some mice. The SDK documentation states that the low word of wParam holds the virtual key information and that the high word holds which button was pressed. I understand how this works in 32bit code, however in 64bit code the wParam is a 64bit unsigned integer. I've seen code that uses Lo(msg.wparam) and Hi(msg.wparam). Does this code still work in 64bits or does something have to change? In other words, does the definition of "high word" change from 32bit to 64bit?
You should have shown the code. Lo and Hi return the low byte and the high byte of a 16-bit value, respectively, so they wouldn't work with 32-bit code, either. Perhaps you meant LoWord and HiWord.
In 64-bit code, you can typecast a 64-bit integer value to Int64Rec:
case Int64Rec(Msg.WParam).Lo of ...
Any code that uses Lo() and Hi() is wrong because those functions return the low and high order bytes of a Word.
The MSDN documentation says the following:
Use the following code to get the information in the wParam parameter:
fwKeys = GET_KEYSTATE_WPARAM (wParam);
fwButton = GET_XBUTTON_WPARAM (wParam);
These macros are defined in the header files as:
#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
In turn, LOWORD and HIWORD are defined as follows:
#define LOWORD(_dw) ((WORD)(((DWORD_PTR)(_dw)) & 0xffff))
#define HIWORD(_dw) ((WORD)((((DWORD_PTR)(_dw)) >> 16) & 0xffff))
These macros are designed to perform the correct task when compiled into both 32 bit and 64 bit code.
In Delphi, the Windows unit contains translations of LoWord and HiWord that perform the same tasks, albeit implemented in a somewhat different manner. So I would implement the following functions:
function GET_KEYSTATE_WPARAM(wParam: WPARAM): Word; inline;
function GET_XBUTTON_WPARAM(wParam: WPARAM): Word; inline;
....
function GET_KEYSTATE_WPARAM(wParam: WPARAM): Word;
begin
Result := LoWord(wParam);
end;
function GET_XBUTTON_WPARAM(wParam: WPARAM): Word;
begin
Result := HiWord(wParam);
end;

How to define an unsigned 64-bit integer in Delphi7?

In Delphi 7, int64s are signed, if I try to declare a hex constant larger than $8000000000000000 (eg, what is really an uint64) I get an error. Can you advise some workarounds, please?
You can make a variant record like so
type muint64 = record
case boolean of
true: (i64 : int64);
false:(lo32, hi32: cardinal);
end;
Now you can just use the cardinals to fill your uint64 with unsigned data.
The other option would be to use code like this:
const almostmaxint64 = $800000045000000;
var muint64: int64;
begin
muint64:= almostmaxint64;
muint64:= muint64 shl 1;
end
Without support from the compiler you don't have many options.
I'm presuming that you wish to pass a value to a function in some external DLL. You'll have to declare the parameter as a signed 64 bit integer, Int64. Then all you can do is pass in the signed value that has the same bit pattern as the desired unsigned value. Build yourself a little converter tool with a compiler that has support for unsigned 64 bit integers.
Traditionally, Broland implementations suffered interoperability issues because lack of largest unsigned supported by target platform. I remember using LongInt values instead of DWORD and waiting for troubles since very early days of Turbo Pascal for Windows. Then was Cardinal happiness, but no, D4 introduced largest integer Int64 in its signed form only. Again.
So your only option is to rely on signed fundamental type Int64 and pray... wait, no, just use Int64Rec typecast to perform arithmetics on least and most significant part separately.
Back to constant declaration:
const
foo = $8000004200000001; // this will work because hexadecimal notation is unsigned by its nature
// however, declared symbol foo becomes signed Int64 value
// attempting to use decimal numeral will result in "Integer constant too large" error
// see "True constants" topic in D7 Help for more details
procedure TForm1.FormCreate(Sender: TObject);
begin
// just to verify
Caption := IntToHex(foo, SizeOf(Int64) * 2);
end;
Unfortunately, the other workaround is to change your compiler. Free Pascal always keeps signed and unsigned types in sync.
This snippet compiles and yields correct result in Borland Delphi Version 15.0 (a.k.a Delphi 7).

File size calculation, Int64, and differences between 32bit and 64bit

I had problems with the following code:
var
FileSize : Int64;
...
FileSize := Info.nFileSizeLow or (Info.nFileSizeHigh shl 32);
I expected it to work because of the Int64 type of the left side of the assignment. But it does not. The partial calculation containing the shl seems to produce an overflow.
So I changed it to:
FileSize := Info.nFileSizeLow or (Int64 (Info.nFileSizeHigh) shl 32);
which works on my 32 bit operating system, but does not work on Vista 64 bit!
Finally,
FileSize := Info.nFileSizeHigh;
FileSize := FileSize shl 32;
FileSize := Info.nFileSizeLow or FileSize;
works on both systems.
Can someone explain the differences in these three versions?
Generally speaking, the type of the expression a * b, where a and b are of type Integer and * is an operator that applies to Integer, is an integer type with the same range as Integer. (I say generally, as an exception is /.) In order for an operator to use 64-bit operations, one or more of the operands must have a range that is only expressible with a 64-bit type. That should cause all the operands to be promoted to 64-bit, and a 64-bit operation performed.
The fact that the left hand side of an assignment is a 64-bit location generally has no effect on the interpretation and typing of the expression on the right hand side of the assignment operator. This is the way it is in almost all languages that I'm aware of that have statically dispatched 32-bit and 64-bit operator overloads (as opposed to polymorphically dispatched operators on arbitrary precision integers or numeric towers etc.); making things behave otherwise would be very surprising behaviour.
For example, arguments to procedure calls are effectively implicit assignments to the parameters. If the left hand side of an assignment could change the interpretation of the expression on the right, we would not know how to interpret the argument to a procedure call without already knowing the definition:
var a, b: Integer;
// ...
P((a shl 16) or b); // 32-bit operation or 64-bit operation?
I do not know why you are seeing different behaviour with your second and third versions of the code. As far as I can see, they should be interpreted the same, and in my tests, they are interpreted the same. If you could provide sample code that works on 32-bit Windows but fails on 64-bit Windows, I could investigate further.
Actually, this is pretty well documented in Delphi 7's help file, under "Integer types":
In general, arithmetic operations on integers return a value of type Integer--which, in its current implementation, is equivalent to the 32-bit Longint. Operations return a value of type Int64 only when performed on one or more Int64 operand. Hence the following code produces incorrect results.
The code example provided:
var
I: Integer;
J: Int64;
...
I := High(Integer);
J := I + 1;
To get an Int64 return value in this situation, cast I as Int64:
...
J := Int64(I) + 1;
First of all FileSize must be defined as UInt64 and not Int64...
UInt64 (not available in early Delphi versions) is an unsigned 64 bit integer, aka a QWORD. This is the expected type for the FileSize (you won't expect a negative file size, won't you?).
IMHO you could have coded - using UInt64 because we don't want to have some values reported as negative:
FileSize := UInt64(Info.nFileSizeLow) or (UInt64(Info.nFileSizeHigh) shl 32));
But under Delphi 7 it produces the same exact code as yours.
FileSize := Info.nFileSizeLow or (Int64(Info.nFileSizeHigh) shl 32));
So there is perhaps some compiler regression. Could you take a look at the asm generated code (step debugger then Alt+F2), and see if there is a difference. But it's unlikely...
In all cases, here is a better (and faster) code:
with Int64Rec(FileSize) do
begin
Lo := Info.nFileSizeLow;
Hi := Info.nFileSizeHigh;
end;
The official MSDN documentation states about the WIN32_FIND_DATA Structure:
nFileSizeHigh: The high-order DWORD value of the file size, in bytes.
This value is zero unless the file size is greater than MAXDWORD.
The size of the file is equal to
(nFileSizeHigh * (MAXDWORD+1)) +
nFileSizeLow.
nFileSizeLow: The low-order DWORD value of the file size, in bytes.
Here is the resulting code:
FileSize := UInt64(Info.nFileSizeLow)+(UInt64(Info.nFileSizeHigh)*UInt64(1 shl 32));
Quite a funny definition, indeed...
This is not really an answer, but it's too long for a comment.
I noticed Delphi gets confused when the result of an expression is to be written into a 64 bit variable, but the operands are 32 bit. I ran into this bug when I was implementing a hash function returning an 64 bit number. Your third variant works because you're first assigning the 64 bit variable, helping Delphi figure out it really needs to do 64 bit arithmetic.
I'm tempted to say both variants (1) and (2) are actually failing because Delphi generates 32 bit arithmetic and then assignes the result to the 64 bit variable. I'm tempted to say the variant that works well on your 32 bit machine benefits from some sort of "unlucky non-failure" (ie: the code is bad, but none the less it produces good results for the given test). The trouble is, COMPILED code doesn't change when moved from a 32bit machine to a 64 bit machine. If the code is the same, the input is the same, you'd have to pin the error on the CPU, but you know you didn't find an bug in your CPU, so you have to fall back and re-think your tests, or pin it on the "unluck non-failure".
test on Delphi 7 and version 2 is OK. Must be bug of later version

Translating Vista WinAPI C++ header for Delphi - any suggestions?

I'm needing to call a Windows API function introduced in Vista from my Delphi app, but I don't have any Delphi headers which describe the function.
Related functions are already documented in the JEDI Windows API library, but not this function.
My C++ is almost non-existent, and I'm struggling to work out the Delphi definitions that correspond to the function and it's parameter as documented on MSDN.
From http://msdn.microsoft.com/en-us/library/aa814417.aspx
NETIOAPI_API GetIpInterfaceEntry(__inout PMIB_IPINTERFACE_ROW Row);
typedef struct _MIB_IPINTERFACE_ROW {
ADDRESS_FAMILY Family;
NET_LUID InterfaceLuid;
NET_IFINDEX InterfaceIndex;
ULONG MaxReassemblySize;
ULONG64 InterfaceIdentifier;
ULONG MinRouterAdvertisementInterval;
ULONG MaxRouterAdvertisementInterval;
BOOLEAN AdvertisingEnabled;
BOOLEAN ForwardingEnabled;
BOOLEAN WeakHostSend;
BOOLEAN WeakHostReceive;
BOOLEAN UseAutomaticMetric;
BOOLEAN UseNeighborUnreachabilityDetection;
BOOLEAN ManagedAddressConfigurationSupported;
BOOLEAN OtherStatefulConfigurationSupported;
BOOLEAN AdvertiseDefaultRoute;
NL_ROUTER_DISCOVERY_BEHAVIOR RouterDiscoveryBehavior;
ULONG DadTransmits;
ULONG BaseReachableTime;
ULONG RetransmitTime;
ULONG PathMtuDiscoveryTimeout;
NL_LINK_LOCAL_ADDRESS_BEHAVIOR LinkLocalAddressBehavior;
ULONG LinkLocalAddressTimeout;
ULONG ZoneIndices[ScopeLevelCount];
ULONG SitePrefixLength;
ULONG Metric;
ULONG NlMtu;
BOOLEAN Connected;
BOOLEAN SupportsWakeUpPatterns;
BOOLEAN SupportsNeighborDiscovery;
BOOLEAN SupportsRouterDiscovery;
ULONG ReachableTime;
NL_INTERFACE_OFFLOAD_ROD TransmitOffload;
NL_INTERFACE_OFFLOAD_ROD ReceiveOffload;
BOOLEAN DisableDefaultRoutes;
}MIB_IPINTERFACE_ROW, *PMIB_IPINTERFACE_ROW;
Among other bits, the bit I'm struggling with at the minute is the ZoneIndices[ScopeLevelCount] field; I can't work out what size the array is supposed to be.
This is what I've defined so far, although I haven't worked out the enums in the original C++ definition yet. I'll be explicitly loading the Windows DLL on Vista and getting the address of the new function to call.
type
PMIB_IPINTERFACE_ROW = ^MIB_IPINTERFACE_ROW;
{$EXTERNALSYM PMIB_IPINTERFACE_ROW}
_MIB_IPINTERFACE_ROW = record
Family: ADDRESS_FAMILY;
InterfaceLuid: NET_LUID;
InterfaceIndex: NET_IFINDEX;
MaxReassemblySize,
InterfaceIdentifier,
MinRouterAdvertisementInterval,
MaxRouterAdvertisementInterval: Cardinal;
AdvertisingEnabled,
ForwardingEnabled,
WeakHostSend,
WeakHostReceive,
UseAutomaticMetric,
UseNeighborUnreachabilityDetection,
ManagedAddressConfigurationSupported,
OtherStatefulConfigurationSupported,
AdvertiseDefaultRoute: LongBool;
RouterDiscoveryBehavior: NL_ROUTER_DISCOVERY_BEHAVIOR;
DadTransmits,
BaseReachableTime,
RetransmitTime,
PathMtuDiscoveryTimeout: Cardinal;
LinkLocalAddressBehavior: NL_LINK_LOCAL_ADDRESS_BEHAVIOR;
LinkLocalAddressTimeout,
ZoneIndices[ScopeLevelCount],
SitePrefixLength,
Metric,
NlMtu: Cardinal;
Connected,
SupportsWakeUpPatterns,
SupportsNeighborDiscovery,
SupportsRouterDiscovery: LongBool;
ReachableTime: Cardinal;
TransmitOffload: NL_INTERFACE_OFFLOAD_ROD;
ReceiveOffload: NL_INTERFACE_OFFLOAD_ROD;
DisableDefaultRoutes: LongBool;
end;
{$EXTERNALSYM _MIB_IPINTERFACE_ROW}
MIB_IPINTERFACE_ROW = _MIB_IPINTERFACE_ROW;
{$EXTERNALSYM MIB_IPINTERFACE_ROW}
TMibIpInterfaceRow = MIB_IPINTERFACE_ROW;
PMibIpInterfaceRow = PMIB_IPINTERFACE_ROW;
const
iphlpapilib = 'iphlpapi.dll';
var
HIpHlpApi: THandle = 0;
GetIpInterfaceEntry: function(const pArpEntry: MIB_IPINTERFACE_ROW): LongInt; stdcall;
{$EXTERNALSYM GetIpInterfaceEntry}
Does anybody out there have suggestions or tips/tricks for translating a function definition like this?
Many thanks,
Conor
The Win32 BOOLEAN type is one byte, but Delphi's LongBool type is four. Use Delphi's ByteBool instead.
Maybe you can try "C 2 pas"
http://cc.embarcadero.com/Item/26951
Also found these tools:
http://www.drbob42.com/delphi/headconv.htm
http://rvelthuis.de/programs/convertpack.html
http://rvelthuis.de/articles/articles-convert.html#cconvs
Hmm. A strange structore. But if you look into w2def.h, you can see that ScopeLevelCount=16. So your array should have 16 elements,
Make sure you use the packed command when defining your record because Delphi aligns complex data types on 2, 4 or 8 byte boundaries by default.
TExample = record
f1: Integer; // start at offset 0x00
f2: Char; // start at offset 0x04
f3: Integer; // start at offset 0x06 or 0x08 depending on alignment
end;
TExample = packed record // this is what c++ would do
f1: Integer; // start at offset 0x00
f2: Char; // start at offset 0x04
f3: Integer; // start at offset 0x05
end;
The ZoneIndices array should be defined like this:
ZoneIndices : array [0..ScopeLevelCount - 1] of Cardinal;
ScopeLevelCount is a constant that is 16
I often used Dr. Bob's Header Converter for this task, but mostly I took the long and tedious way of manually performing the conversion, because it helped me to understand the API better. (Because I was going to use it and I have to familiarize myself with it anyway)
Also see this article: http://www.delphi-jedi.org/api-howto.html
In general it's best not to put to much hopes on a header conversion tool, because C++ is a very powerful and complex language. Most conversion tools I tested only supported a subset of C++ and its preprocessor, thus making it necessary to manually make fixes to the generated source.
you can investigate some already translated APIs/structures that related to this subject and convert it yourself. for example this one
I don't see any field of type ULONG64 in the translation, but I do in the original.
Further, FPC also has an header converter which works fine for structs. Typically windows api structures are packed.
In doubt, use some free msvc product to write the sizeof(structure) and do the same under pascal. If that matches, and you still have doubts, calculate field offsets with a bit of pointer magic and compare them.

Delphi Array Alignment set to 4, 8, or 16 byte boundaries?

I would like to use the FFTW C library from Delphi 2009 and according to this documentation;
http://www.fftw.org/install/fftw_usage_from_delphi.txt
to increase the performance inside the FFTW library (such that it can use SIMD extensions) arrays passed in of either Single (float) or Double (double) need to be aligned either at 4 or 8 byte boundaries. I found documentation talking about alignment of record structures, but nothing specific about arrays. Is there a way to do this in Delphi 2009.
So the code (copied from the above documentation) would look like this;
var
in, out : Array of Single; // Array aligned at 4 byte boundary
plan : Pointer;
{$APPTYPE CONSOLE}
begin
...
SetLength(in, N);
SetLength(out, N);
plan := _fftwf_plan_dft_1d(dataLength, #in[0], #out[0],
FFTW_FORWARD, FFTW_ESTIMATE);
Also in the above documentation they talk about 8 and 16 byte boundaries but it looks to me it should be 4 and 8 byte boundaries, if any could clear that up to that would be great.
Thanks,
Bruce
Note that you can create data structures with any custom alignment you might need. For example to align your FFT data on 128 byte boundaries:
procedure TForm1.Button1Click(Sender: TObject);
type
TFFTData = array[0..63535] of double;
PFFTData = ^TFFTData;
var
Buffer: pointer;
FFTDataPtr: PFFTData;
i: integer;
const
Alignment = 128; // needs to be power of 2
begin
GetMem(Buffer, SizeOf(TFFTData) + Alignment);
try
FFTDataPtr := PFFTData((LongWord(Buffer) + Alignment - 1)
and not (Alignment - 1));
// use data...
for i := Low(TFFTData) to High(TFFTData) do
FFTDataPtr[i] := i * pi;
finally
FreeMem(Buffer);
end;
end;
Edit:
Regarding the comment about twice the memory being allocated: The stack variable FFTData is of type PFFTData, not of TFFTData, so it's a pointer. It's not that obvious because of the syntax enhancement allowing to omit the ^ for dereferencing the pointer. The memory is allocated with GetMem(), and to work with the proper type instead of the untyped memory block the typecast is employed. I should probably have called it FFTDataPtr.
Delphi provides no way to control the alignment of any memory it allocates. You're left to either rely on the documented behavior for the memory manager currently installed, or allocate memory with some slack space and then align it yourself, as Mghie demonstrates.
If you're concerned that Delphi's memory manager is not providing the desired alignment for dynamic arrays, then you can go ahead and use the memory functions provided by the DLL. The note you cite mentions _fftwf_malloc and _fftwf_free, but then it gives some kind of warning that memory allocated from _fftwf_malloc "may not be accessed directly from Delphi." That can't be what the authors meant to say, though, because that's not how memory works in Windows. The authors probably meant to say that memory allocated by _fftwf_malloc cannot be freed by Delphi's FreeMem, and memory allocated by Delphi's GetMem cannot be freed by _fftwf_free. That's nothing special, though; you always need to keep your memory-management functions paired together.
If you use _fftwf_malloc to get your array, then you can access it through an ordinary pointer type. For example:
var
dataIn, dataOut: PDouble;
begin
dataIn := _fftwf_malloc(...);
dataOut := _fftwf_malloc(...);
_fftwf_plan_dft_1d(dataLength, dataIn, dataOut,
FFTW_FORWARD, FFTW_ESTIMATE);
As of Delphi 2009, you can even use array syntax on those pointers:
dataIn[0] := 3.5;
dataIn[2] := 7.3;
In order to enable that, use the {$POINTERMATH ON} compiler directive; it's not enabled by default except for the character-pointer types.
The disadvantage to manually allocating arrays like this is that you lose range checking. If you index beyond the end of an array, you won't get an easy-to-recognize ERangeError exception anymore. You'll get corrupted memory, access violations, or mysteriously crashing programs instead.
Heap blocks are iirc always aligned to 16-byte bounderies by FastMM (the old D7 memmanager aligned to 8). I don't know about sharemem, since I don't use it.
And dynamic arrays are heap based structures. OTOH dyn arrays could maybe become unaligned (from 16 to 8) because there is a length and ref count prefixed. Easiest is to simply print
ptruint(#in[0]) in hex and see if the end is 0 or 8. (*)
Note that there are fftw headers in FPC. ( packages/fftw), afaik it was recently fixed for 64-bit even.
I'm not aware of Stack alignment directives in Delphi. Maybe they are automatically "naturally" aligned though.
(*) ptruint is FPC speak for an unsigned integer type that is sizeof(pointer) large. cardinal on 32-bit, qword on 64-bit.
This is another possible variant of mghie's solution:
procedure TForm1.Button1Click(Sender: TObject);
type
TFFTData = array [0..0] of Double;
PFFTData = ^TFFTData;
var
AllocatedBuffer: Pointer;
AlignedArray: PFFTData;
i: Integer;
const
cFFTDataSize=63536;
begin
GetMem(AllocatedBuffer, cFFTDataSize*SizeOf(Double) + 16); // e.g 16 Bytes boudaries alignement
try
AlignedArray := PFFTData((Integer(AllocatedBuffer) and $FFFFFFF0) + 16);
// use data...
for i := 0 to cFFTDataSize-1 do
AlignedArray[i] := i * Pi;
finally
FreeMem(AllocatedBuffer);
end;
end;
I've refactored the piece of code to make it more meaningfull and make use of a similar manual alignement fix up technique.

Resources