Home > database >  NetWkstaGetInfo ACCESS_VIOLATION under WIN64
NetWkstaGetInfo ACCESS_VIOLATION under WIN64

Time:04-11

I'm have code, which works fine during many years under WIN32. But yesterday, after compiling under WIN64 I'm got strange ACCESS_VIOLATION error when trying get wki100_langroup field. Where wrong this code? (Computer not in domain and in Delphi 11 debug window I can see, that this field is empty)

const
  NERR_SUCCESS = 0;

type
  WKSTA_INFO_100 = record
    wki100_platform_id: DWORD;
    wki100_computername: LPWSTR;
    wki100_langroup: LPWSTR;
    wki100_ver_major: DWORD;
    wki100_ver_minor: DWORD;
  end;
  LPWKSTA_INFO_100 = ^WKSTA_INFO_100;

function NetWkstaGetInfo(ServerName: LPWSTR; Level: DWORD; var BufPtr: Pointer): DWORD; stdcall;
  external 'netapi32.dll' Name 'NetWkstaGetInfo';

function GetDomain: string;
var
  PBuf: Pointer;
  Res: Integer;
begin
  Result := '';
  Res := NetWkstaGetInfo(nil, 100, PBuf);
  if (Res = NERR_Success) then begin
    Result := LPWKSTA_INFO_100(PBuf)^.wki100_langroup; // ACCESS_VIOLATION here
    if Assigned(PBuf) then
      NetApiBufferFree(PBuf);
  end;
end;

Update: After changing Pointer to PByte I have the same exception

function NetWkstaGetInfo(ServerName: LPWSTR; Level: DWORD; BufPtr: PByte): DWORD; stdcall;
  external 'netapi32.dll' Name 'NetWkstaGetInfo';

function GetDomain: string;
var
  PBuf: PByte;
  Res: Integer;
begin
  Result := '';
  Res := NetWkstaGetInfo(nil, 100, @PBuf);
  if (Res = NERR_Success) then begin
    Result := LPWKSTA_INFO_100(PBuf)^.wki100_langroup; // ACCESS_VIOLATION here
    if Assigned(PBuf) then
      NetApiBufferFree(PBuf);
  end;
end;

Screenshots from Win32: Win32

and Win64 breakpoints: enter image description here

CodePudding user response:

The symptoms suggest that some other code changed default record alignment for WKSTA_INFO_100 record type.

Under 32-bit compiler that wouldn't have an impact because all values in the record are also 32-bit therefore they will be correctly aligned even if other alignment size is specified.

Under 64-bit compiler DWORD is 32-bit, while LPWSTR is 64-bit. With default 8 byte alignment that means there will be 4 padding bytes inserted after wki100_platform_id. If some other alignment is used following fields will not be at correct positions.

To correct this you need to specify 8 byte alignment {$A8} before type declaration.

type
{$A8}
  WKSTA_INFO_100 = record
    wki100_platform_id: DWORD;
    wki100_computername: LPWSTR;
    wki100_langroup: LPWSTR;
    wki100_ver_major: DWORD;
    wki100_ver_minor: DWORD;
  end;
  • Related