views:

473

answers:

1

Hi.

I would like to declare an external function from the kernel32.dll library whose name is GetTickCount64. As far as I know, it is defined only in Vista and in later Windows versions. This means that when I define the function as follows:

function GetTickCount64: int64; external kernel32 name 'GetTickCount64';

I will certainly not be able to run my application on previous versions of Windows because of error generated on application startup.

Is there a workaround to that problem? Let's say I would like not to include that function when it does not exist and then use some substitute function in my code. How to do that? Are there any compiler directives that would help? I gues the definition would have to be surrounded by such directive and I would also have to use some directives wherever I use the GetTickCount64 founction, right?

Your help will be appreciated. Thanks in advance.

Mariusz.

+10  A: 

Declare a function pointer of that type, and then load the function at run time with LoadLibrary or GetModuleHandle and GetProcAddress. You can find several examples of the technique in the Delphi source code; look at TlHelp32.pas, which loads the ToolHelp library, which isn't available on older versions of Windows NT.

interface

function GetTickCount64: Int64;

implementation

uses Windows, SysUtils;

type
   // Don't forget stdcall for API functions.
  TGetTickCount64 = function: Int64; stdcall;

var
  _GetTickCount64: TGetTickCount64;

// Load the Vista function if available, and call it.
// Raise EOSError if the function isn't available.
function GetTickCount64: Int64;
var
  kernel32: HModule;
begin
  if not Assigned(_GetTickCount64) then begin
    // Kernel32 is always loaded already, so use GetModuleHandle
    // instead of LoadLibrary
    kernel32 := GetModuleHandle('kernel32');
    if kernel32 = 0 then
      RaiseLastOSError;
    @_GetTickCount := GetProcAddress(kernel32, 'GetTickCount64');
    if not Assigned(_GetTickCount64) then
      RaiseLastOSError;
  end;
  Result := _GetTickCount64;
end;
Rob Kennedy
Thanks for your answer. I think it is what I was looking for.I have a question, though. I would like to modify the condition as follows: if not Assigned(_GetTickCount64) then @_GetTickCount64 := @GetTickCount;Is that correct? As you can see, I used the function GetTickCount which is declared by default in the "Windows" module as a substitute when GetTickCount64 is not defined. I understand that I can assign any function that returns int64 to the _GetTickCount64 variable, right? Or does it have to be an external function only? I do not know the stdcall key word yet :-(.
Mariusz
You can assign a DWord to an Int64, but you cannot assign "pointer to function returning DWord" to a "pointer to function returning Int64." You could write another function matching GetTickCount64's signature, and in it call GetTickCount. Assign a pointer to *that* function to _GetTickCount64 if you find the real function missing.
Rob Kennedy