WIN64 下的 NetWkstaGetInfo ACCESS_VIOLATION

NetWkstaGetInfo ACCESS_VIOLATION under WIN64

我有代码,多年来在 WIN32 下运行良好。但是昨天,在 WIN64 下编译后,我在尝试获取 wki100_langroup 字段时遇到了奇怪的 ACCESS_VIOLATION 错误。这段代码哪里错了? (计算机不在域和 Delphi 11 调试 window 我可以看到,这个字段是空的)

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;

更新: 将指针更改为 PByte 后,我有同样的异常

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;

来自 Win32 的屏幕截图:

和Win64断点:

症状表明某些其他代码更改了 WKSTA_INFO_100 记录类型的默认记录对齐方式。

在 32 位编译器下不会产生影响,因为记录中的所有值也是 32 位的,因此即使指定了其他对齐大小,它们也会正确对齐。

在 64 位编译器下 DWORD 是 32 位的,而 LPWSTR 是 64 位的。默认 8 字节对齐,这意味着将在 wki100_platform_id 之后插入 4 个填充字节。如果使用其他对齐方式,以下字段将不会位于正确的位置。

要更正此问题,您需要在类型声明之前指定 8 字节对齐 {$A8}

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;