简体   繁体   中英

Calling GetStringTypeW from non-unicode Delphi (7)

I'm attempting to call GetStringTypeW from a non-unicode delphi application and, no matter what I do, I get ERROR_INVALID_FLAGS back. I couldn't find any code sample of that function in use either.

I also had to redifine the function header because the ones provided in windows.pas incorrectly identifies the 3rd parameter as a boolean (it's an INT)

here is my definition for the function:

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

(For some reason, that function isn't defined as stdcall. Trying it to define it as stdcall will result in an access violation.)

And my call:

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;
{..}

The error I get is

System Error.  Code: 1004.
Invalid flags.

I've verified that CT_CTYPE1 is equal to 1.

Does anyone know what could be wrong or have a code sample for using this function ?

The declaration in Windows.pas is indeed wrong, but your correction is wrong, too. You've fixed the parameter types, but you need to fix the calling convention. It should be stdcall :

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

Without the calling-convention fix, Delphi puts most of the parameters in registers, but the OS expects to find them on the stack. The stack doesn't contain the right values at the right places, to it fails. A bad calling convention can also lead to access violations because the stack is left in an inconsistent state, but since you immediately throw your own exception anyway, that might conceal the stack problems.

When you use stdcall , you get an access violation because you're passing a character and claiming it's a pointer. The OS attempts to dereference the "pointer," but since the character value doesn't represent a valid address, it fails. Type-cast the whole string, not just one character, when you call the function:

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

Your second parameter is wrong. You are type-casting a single WideChar value to a PWideChar , instead of obtaining the memory address of that WideChar . In other words, change this:

PWideChar(APassword[1])

To this:

PWideChar(APassword)

Or this (only if the length of APassword is never 0):

@APassword[1]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM