从非 unicode Delphi 调用 GetStringTypeW (7)



我试图从一个非Unicode delphi应用程序调用GetStringTypeW,无论我做什么,我都会得到ERROR_INVALID_FLAGS。我也找不到正在使用的函数的任何代码示例。

我还必须重新定义函数标头,因为 windows.pas 中提供的函数标头错误地将第三个参数标识为布尔值(它是一个 INT)

这是我对该函数的定义:

function GetStringTypeW(dwInfoType: DWORD; lpSrcStr: PWideChar; cchSrc: Integer; lpCharType: Pointer): BOOL;

(出于某种原因,该函数未定义为 stdcall。尝试将其定义为标准调用将导致访问冲突。

我的电话:

var
  aCharType: Array of WORD;
  APassword: WideString
begin
{..}
    SetLength(aCharType, Length(APassword));
    if not GetStringTypeW(CT_CTYPE1, PWideChar(APassword[1]), Length(APassword), @aCharType[0]) then
      RaiseLastOSError;
{..}

我得到的错误是

System Error.  Code: 1004.
Invalid flags.

我已经验证了CT_CTYPE1等于 1。

有谁知道可能出了什么问题或有使用此函数的代码示例?

Windows.pas 中的声明确实是错误的,但您的更正也是错误的。你已修复参数类型,但需要修复调用约定。应该stdcall

function GetStringTypeW(
  dwInfoType: DWORD;
  const lpSrcStr: PWideChar;
  cchSrc: Integer;
  lpCharType: PWordArray
  ): BOOL; stdacll;

如果没有调用约定修复,Delphi 会将大部分参数放在寄存器中,但操作系统希望在堆栈上找到它们。堆栈在正确的位置不包含正确的值,导致失败。错误的调用约定也可能导致访问冲突,因为堆栈处于不一致状态,但由于您无论如何都会立即抛出自己的异常,这可能会隐藏堆栈问题。

当您使用 stdcall 时,您会收到访问冲突,因为您传递了一个字符并声称它是一个指针。OS 尝试取消引用"指针",但由于字符值不表示有效地址,因此失败。调用函数时,对整个字符串进行类型转换,而不仅仅是一个字符:

GetStringTypeW(CT_CTYPE1, PWideChar(APassword), Length(APassword), PWordArray(aCharType))

你的第二个参数是错误的。 您正在将单个WideChar值类型转换为PWideChar,而不是获取该WideChar的内存地址。 换句话说,更改以下内容:

PWideChar(APassword[1])

对此:

PWideChar(APassword)

或者这样(仅当 APassword 的长度从不为 0 时):

@APassword[1]

最新更新