delphi - call external WinAPI function

跟風遠走 提交于 2019-12-10 22:15:46

问题


I'm trying to call IsNativeVhdBoot function but i get error message The parameter is incorrect.

function IsNativeVhdBoot(var NativeVhdBoot:PBOOL):BOOL; external Kernel32 name 'IsNativeVhdBoot';

function _IsNativeVhdBoot:Boolean;
var
  pB:PBOOL;
begin
  Result := False;
  if IsNativeVhdBoot(pB) then
    Result := pB^
  else RaiseLastOSError;
end;

I have also tried to call it this way

function __IsNativeVhdBoot: Boolean;
type
  TIsNativeVhdBoot = function(
    var NativeVhdBoot: pBOOL
  ): BOOL; stdcall;
var
  bNativeVhdBoot: pBOOL;
  NativeVhdBoot : TIsNativeVhdBoot;
begin
  Result := False;
  NativeVhdBoot := GetProcAddress(GetModuleHandle(kernel32), 'IsNativeVhdBoot');
  if (@NativeVhdBoot <> nil) then
  begin
    if not NativeVhdBoot(bNativeVhdBoot) then
      RaiseLastOSError;
    Result := bNativeVhdBoot^;
  end
  else
    RaiseLastOSError;
end;

My questions is

  1. What I'm doing wrong to call the above function.
  2. When Calling an extranl WinAPI in delphi what is the difference between calling it function Foo():BOOL; external Kernel32 name 'Foo'; and type TFoo = function(): BOOL; stdcall;

Because i usually do the calls like the first method but when i get the above error message i searched how to call external function and i found the other method.

Update

Tested the same function in C++ and i got the same error, my code was as the following

#include "stdafx.h"
#include "Windows.h"

int _tmain(int argc, _TCHAR* argv[])
{
    BOOL Result = false;
    SetLastError(0);
    if (IsNativeVhdBoot(&Result)) {
        if (Result) {
            printf_s("Running inside VHD\n");
        }
        else
            printf_s("Running inside physical disk drive\n");
    }
    else
        printf("IsNativeVhdBoot failed with error %d.\n", GetLastError());
    return 0;
}

回答1:


In your first try, you have a calling convention mismatch, documentation you linked states it to be 'stdcall'. It would seem, however, from the comments to the question and this answer that this is not the reason you get the "parameter is incorrect" error. The call seems to set this error in all conditions.

In both of the tries, you have an extra indirection level with your parameter. The documentation states that the API is expecting an address of a BOOL variable. Explanation of the parameter is actually inconsistent with the declaration in the documentation which suggests a pointer to a pointer to a BOOL. However the actual declaration in 'winbase.h' is different than the one in the documentation and is in accordance with the wording:

WINBASEAPI
BOOL
WINAPI
IsNativeVhdBoot (
    _Out_ PBOOL NativeVhdBoot
    );

So the parameter is a 'var BOOL' or a 'PBOOL', not a 'var PBOOL'. Should you use 'PBOOL', you have to pass an existing BOOL variable's address, not a pointer that doesn't point to anywhere as in your first snippet.

At this point one should note that, it actually doesn't matter, as the API does not seem to be setting the 'out' parameter. This maybe somewhat expected as the documentation is confusing in that it states that the result will both be set to the parameter, and will be returned as the function result. Which is unusual...

Notice that the return value of the function does not indicate that the function failed or succeeded - according to the documentation. This is inconsistent in itself as the documentation also suggests to call GetLastError, normally GetLastError is only called when a function fails and here we have no means to know if it failed or not before calling it. In any case, the implication is that you have to remove the statement that raises an exception at a false return.


For the second question, your first declaration statically loads the library, the second snippet dynamically loads the library. For more information, refer to documentation. As mentioned above, you have an additional difference in that the first one has register calling convention, but that difference is not meant to be.



来源:https://stackoverflow.com/questions/36378993/delphi-call-external-winapi-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!