Home > OS >  Win32API LogonUserA vs LogonUserW
Win32API LogonUserA vs LogonUserW

Time:06-14

So for the past days I have been stuck with LogonUserA which always threw an error 1008 - ERROR_NO_TOKEN "An attempt was made to reference a token that does not exist.". It did not matter what logon type or logon provider I passed to the function - it could be interactive/network logon for domain profiles or even interactive logon for a local account. It just always failed.

After I had almost pulled my hair out, I checked out the LogonUserW function. They both have identical signatures and their documentation is absolutely the same to the letter.

LogonUserA https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera

LogonUserW https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonuserw

These were my signatures

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUserA(
    string lpszUsername,
    string lpszDomain,
    string lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    out IntPtr phToken
    );
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUserW(
    string lpszUsername,
    string lpszDomain,
    string lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    out IntPtr phToken
    );

I have also tried using phToken as a ref for LogonUserA, but it did not change anything.

Now, my question is, is there someone who knows the difference? Or perhaps the reason for the 1008 while using LogonUserA?

Thanks!

CodePudding user response:

  • Almost every Win32 function that handles strings or text exists as either an "A" or a "W" function.

    • The "A" functions accept ANSI text in char buffers, and were used in the Windows 9x family (95/98/98SE/ME) which lacked true Unicode support within the OS.
    • The "W" functions ("W" for "Wide Character", i.e. 16-bit) accept UTF-16 text in wchar_t buffers, and originated in the Windows NT family.
  • Generally speaking, you should not be using "A" functions anymore, simply because they won't work if you need to handle Unicode text input - though Windows still supports "A" functions for the sake of backwards compatibility.

  • When you use [DllImport] on a Win32 function that accepts string/text input you you need to specify the CharSet parameter:

  • Also, imported Win32 BOOL functions should additionally be annotated with [return: MarshalAs(UnmanagedType.Bool)] to ensure correct handling of return values.

So change your code to this:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
[return: MarshalAs( UnmanagedType.Bool )]
public static extern bool LogonUserA(
    string     lpszUsername,
    string?    lpszDomain,
    string     lpszPassword,
    int        dwLogonType,
    int        dwLogonProvider,
    out IntPtr phToken
);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs( UnmanagedType.Bool )]
public static extern bool LogonUserW(
    string     lpszUsername,
    string?    lpszDomain,
    string     lpszPassword,
    int        dwLogonType,
    int        dwLogonProvider,
    out IntPtr phToken
);
  • Related