Created
November 11, 2021 00:59
-
-
Save khchen/e2697a9b809b099880c682d92754f1ed to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[ | |
Author: Ward | |
Example of GetUserName | |
References: | |
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getusernamea | |
]# | |
import winim/lean | |
import winim/inc/lm # for UNLEN | |
# Method 1: create a nim string as a buffer | |
# This is the easiest way to understand, however, it has two shortcomings. | |
# 1. It only works for ansi string API. | |
# 2. It store ansi string in nim string, which should be utf8 encoding. This may be wrong. | |
block: | |
var | |
buffer = newString(UNLEN + 1) | |
cb = DWORD buffer.len | |
GetUserNameA(&buffer, &cb) | |
buffer.setLen(cb - 1) # cb including the terminating null character | |
echo buffer | |
# Method 2: create a wstring or mstring as a buffer | |
# wstring is unicode string (aka wide character string), mstring is ansi string | |
# (aka multibyte character string), both of them are defined in winstr. | |
# This method has no encoding problem, but works only for specific API. | |
block: | |
var | |
buffer = newMString(UNLEN + 1) # return a mstring | |
cb = DWORD buffer.len | |
GetUserNameA(&buffer, &cb) | |
buffer.setLen(cb - 1) | |
echo $buffer # `$` convert mstring (ansi) to nim string (utf8). | |
block: | |
var | |
buffer = newWString(UNLEN + 1) # return a wstring | |
cb = DWORD buffer.len | |
GetUserNameW(&buffer, &cb) | |
buffer.setLen(cb - 1) | |
echo $buffer # `$` convert wstring (unicode) to nim string (utf8). | |
# Method 3: create a buffer by `T` template | |
# Nim/winim use unicode API by default, but it can be switched to ansi API if | |
# compiles with -d:useWinAnsi. So there is a T template. | |
# T template accept: | |
# 1: string => generate wstring or mstring depend on conditional symbol | |
# 2: Natural (range[0 .. high(int)]) => generate wstring buffer or mstring buffer | |
# This should be the best way for winim. It always works without encoding problem. | |
block: | |
var | |
buffer = T(UNLEN + 1) | |
cb = DWORD buffer.len | |
GetUserName(&buffer, &cb) | |
buffer.setLen(cb - 1) | |
echo $buffer | |
# More exercise... Using array as a buffer | |
block: | |
# TCHAR and LPTSTR are also automatically switched | |
var | |
buffer: array[UNLEN + 1, TCHAR] | |
cb = DWORD buffer.len | |
GetUserName(&buffer[0], &cb) | |
echo $cast[LPTSTR](&buffer[0]) # Use `$` and cast, only for null-terminated string | |
echo nullTerminated(%$buffer) # %$ Always treat `openArray[SomeChar]` as string, | |
# This way can deal with binary strings | |
echo %$(buffer[0..<cb-1]) # Should be the optimized way | |
# Using seq as a buffer | |
block: | |
var | |
buffer = newSeq[TCHAR](UNLEN + 1) | |
cb = DWORD buffer.len | |
GetUserName(&buffer[0], &cb) | |
echo $cast[LPTSTR](&buffer[0]) | |
echo nullTerminated(%$buffer) | |
echo %$(buffer[0..<cb-1]) | |
# Using memory block as a buffer | |
block: | |
var | |
buffer = alloc0(sizeof(TCHAR) * (UNLEN + 1)) | |
cb: DWORD = UNLEN + 1 | |
defer: | |
dealloc(buffer) | |
GetUserName(cast[LPTSTR](buffer), &cb) | |
echo $cast[LPTSTR](buffer) | |
echo %$cast[ptr UncheckedArray[TCHAR]](buffer).toOpenArray(0, cb-2) # <- wtf, don't ask... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment