我试图从一个非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]