win64下的netwkstagetinfo Access_violation

发布于 2025-01-20 18:17:20 字数 1724 浏览 0 评论 0原文

我有代码,在 WIN32 下可以正常工作很多年。但是昨天,在 WIN64 下编译后,在尝试获取 wki100_langroup 字段时,我遇到了奇怪的 ACCESS_VIOLATION 错误。这段代码哪里错了? (计算机不在域中,在 Delphi 11 调试窗口中我可以看到,该字段为空)

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 屏幕截图: Win32

和 Win64 断点: 输入图片此处描述

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光礼记 2025-01-27 18:17:20

症状表明,其他一些代码更改了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;

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文