Reputation: 3402
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 ?
Upvotes: 1
Views: 394
Reputation: 163257
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))
Upvotes: 4
Reputation: 595792
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]
Upvotes: 1