1

我正在尝试从非 unicode delphi 应用程序调用 GetStringTypeW,无论我做什么,我都会返回 ERROR_INVALID_FLAGS。我也找不到该函数的任何代码示例。

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

这是我对函数的定义:

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

(由于某种原因,该函数未定义为 stdcall。尝试将其定义为 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。

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

4

2 回答 2

4

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

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

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

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

GetStringTypeW(CT_CTYPE1, PWideChar(APassword), Length(APassword), PWordArray(aCharType))
于 2013-09-18T18:32:59.323 回答
1

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

PWideChar(APassword[1])

对此:

PWideChar(APassword)

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

@APassword[1]
于 2013-09-17T18:14:17.743 回答