Coding with Ansi & Unicode compatibility question Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Coding with Ansi & Unicode compatibility question

12 Dec 2018, 19:33

Hey all,

After getting the libHaru library to work with unicode, i'm finally able to switch one of my programs to U32, and merge it with another that already required unicode. So i've been tackling a couple other functions to get them to work with all versions, A|U32|64

Started with it working in ansi, made it work in unicode but broke ansi, now i'm trying to make sense of the W/A suffix so i can understand better and make it support either

Simply, ansi works with dllcalls to:
advapi32\LookupAccountNameA
asvapi32\ConvertSidToStringSidA
lstrlen
lstrcpy

while unicode works with:
advapi32\LookupAccountName (or +W)
asvapi32\ConvertSidToStringSid (or +W)
lstrlenW (but not without the W??)
lstrcpyW (")


Thanks for any explanation
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Coding with Ansi & Unicode compatibility question

12 Dec 2018, 19:57

- The main things to be aware of are: Str/AStr/WStr, and also Ptr.
- All 3 of these will work on both AHK ANSI and AHK Unicode.

Code: Select all

DllCall("user32\MessageBox", Ptr,0, Str,"prompt", Str,"title", UInt,0)
DllCall("user32\MessageBoxA", Ptr,0, AStr,"prompt", AStr,"title", UInt,0)
DllCall("user32\MessageBoxW", Ptr,0, WStr,"prompt", WStr,"title", UInt,0)
- In these examples instead of Str/AStr/WStr, we use Ptr. The difference is that we're manually doing the sort of work that AStr/WStr do for us. Again, all 3 will work on both AHK ANSI and AHK Unicode.

Code: Select all

vText := "prompt"
VarSetCapacity(vTextA, StrLen(vText)+1)
VarSetCapacity(vTextW, StrLen(vText)*2+2)
StrPut(vText, &vTextA, "CP0")
StrPut(vText, &vTextW, "UTF-16")

DllCall("user32\MessageBox", Ptr,0, Ptr,&vText, Str,"title", UInt,0)
DllCall("user32\MessageBoxA", Ptr,0, Ptr,&vTextA, AStr,"title", UInt,0)
DllCall("user32\MessageBoxW", Ptr,0, Ptr,&vTextW, WStr,"title", UInt,0)
- Most of the time you have FuncA and FuncW, and if you specify Func, AHK checks for Func, and if it doesn't find it, AHK Unicode tries FuncW, and AHK ANSI tries FuncA.
- Other times the situation is slightly different. One possibility is that you have Func (ANSI) and FuncW (Unicode). And specifying Func when using AHK Unicode will give you the wrong answer, although for AHK ANSI, Func would work.

- It can be useful to see the lists of functions for a dll.
DllListExports() - List of Function exports of a DLL - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=4563
- The dlls and dll functions that I use most commonly are listed here, and are typically CamelCase. The main omission is msvcrt.dll which often uses lowercase names, and requires the use of Cdecl when using DllCall.
WinApi
https://hotkeyit.github.io/v2/docs/commands/WinApi.htm
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Coding with Ansi & Unicode compatibility question

12 Dec 2018, 20:24

Thanks for the explanation. That all makes sense, I guess lstrcpy and lstrlen fall into this category:
- Other times the situation is slightly different. One possibility is that you have Func (ANSI) and FuncW (Unicode). And specifying Func when using AHK Unicode will give you the wrong answer, although for AHK ANSI, Func would work.
The following works in either Ansi or Unicode, but if i change it to lstrlen and lstrcpy without the W suffix, it continues to work in Ansi but no longer works in Unicode??

Code: Select all

MsgBox, % A_UserName " = " GetStandardUserSID()

GetStandardUserSID() {
 wtsapi32 := DllCall("LoadLibrary", Str, "wtsapi32.dll", Ptr)
 DllCall("wtsapi32\WTSEnumerateSessionsEx", Ptr, 0, "UPtr*", 1, UPtr, 0, "Ptr*", pSessionInfo, "UPtr*", wtsSessionCount)
 Loop % wtsSessionCount {
  _ := ((A_PtrSize == 8 ? 56 : 32) * (A_Index - 1)) + 8 + (A_PtrSize * 3)
  If (UserName := StrGet(NumGet(pSessionInfo+0, _, "Ptr"),, A_IsUnicode ? "UTF-16" : "CP0"))
   Break
 }
 DllCall("wtsapi32\WTSFreeMemoryEx", UPtr, 2, Ptr, pSessionInfo, UPtr, wtsSessionCount)
 DllCall("FreeLibrary", Ptr, wtsapi32)
 DllCall("advapi32\LookupAccountName", Str, System, Str, UserName, UPtr, 0, UPtrP, nSizeSID, UPtr, 0, UPtrP, nSizeRDN, UPtrP, eUser)
 VarSetCapacity(SID, nSizeSID, 0)
 VarSetCapacity(RDN, nSizeRDN, 0)
 DllCall("advapi32\LookupAccountName", Str, S, Str, UserName, Str, SID, UPtrP, nSizeSID, Str, RDN, UPtrP, nSizeRDN, UPtrP, eUser)
 DllCall("advapi32\ConvertSidToStringSid", Str, SID, UPtrP, pString)
 VarSetCapacity(sSid, DllCall("lstrlenW", UPtr, pString)*2)
 DllCall("lstrcpyW", Str, sSid, UPtr, pString)
 DllCall("LocalFree", UPtr, pString)
Return sSid
}

I guess its just a matter of looking up the problematic functions?
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Coding with Ansi & Unicode compatibility question  Topic is solved

12 Dec 2018, 20:36

- I would suppose that lstrlen starts at the first byte and searches for the first null byte.
- And that lstrlenW starts at the first short and searches for the first null short.
- And so lstrlenW would work fine to handle UTF-16 strings, and might go beyond what it needed to when handling ANSI strings.
- In theory in AHK ANSI, lstrlenW could search forever for a null short, never find one, check in memory it didn't have permission for (something like that) and cause a crash.
- Also in AHK ANSI, lstrlenW might try to copy more text than the variable could handle and cause a crash.
- In general, functions that expect a null-terminated string, that receive strings that aren't null-terminated, that can cause a crash. Using VarSetCapacity with extra nulls on the end should avoid such a situation.
- I usually use MSDN to confirm whether functions handle Unicode/ANSI etc.
Last edited by jeeswg on 09 Jan 2019, 23:25, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Coding with Ansi & Unicode compatibility question

13 Dec 2018, 00:29

Makes sense, thanks!
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: alawsareps, Google [Bot], mebelantikjaya, mikeyww, RussF and 309 guests