Hello, so i want to port a library that I wrote in go and that uses winapi to nim. However, I encountered a problem that I didn't have in go, the same calls in go return expected results but in nim i always get access denied. I can't figure out why this is happening, for example in go this function will return the process name:
hNDL, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, PID)
defer windows.CloseHandle(hNDL)
if err != nil {
fmt.Println(err)
}
var pName uint16
err = windows.GetModuleBaseName(hNDL, 0, &pName, 260)
if err != nil {
fmt.Println(err)
}
ppName := windows.UTF16PtrToString(&pName)
fmt.Println(ppName)
While in nim the same call will give access denied:
proc test() =
var hNDL = OpenProcess(cast[DWORD](PROCESS_QUERY_INFORMATION), FALSE, cast[DWORD](PID))
defer: CloseHandle(hNDL)
var pName: wstring
if GetModuleBaseNameW(hNDL, 0, pName, 260) == 0:
echo GetLastError()
else:
echo pName
when isMainModule:
test()
I'm running as administrator, additionally I've disabled antivirus (defender) and also tried giving additional permissions (with succes):
proc test() =
var hToken: HANDLE
var ldbg: LUID
var token: TOKEN_PRIVILEGES
var pTknPrev: PTOKEN_PRIVILEGES
if OpenProcessToken(GetCurrentProcess(), cast[DWORD](TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hToken.addr) != 0:
if LookupPrivilegeValue("", SE_DEBUG_NAME, ldbg.addr) != 0:
echo ldbg
token.PrivilegeCount = 1
token.Privileges[0].Luid = ldbg
token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
if AdjustTokenPrivileges(hToken, FALSE, token.addr, cast[DWORD](sizeof(token)), pTknPrev, cast[PDWORD](0)) != 0:
echo "ok"
else:
echo "fail"
echo GetLastError()
else:
echo GetLastError()
defer: CloseHandle(hToken)
var hNDL = OpenProcess(cast[DWORD](PROCESS_QUERY_INFORMATION), FALSE, cast[DWORD](PID))
defer: CloseHandle(hNDL)
var pName: wstring
if GetModuleBaseNameW(hNDL, 0, pName, 260) == 0:
echo GetLastError()
else:
echo pName
when isMainModule:
test()
And each time I get access denied. I am not trying to read sys process, but for example notepad. Could someone familiar with winapi please direct me what else I should do?
Why would
var pName: wstring
if GetModuleBaseNameW(hNDL, 0, pName, 260) == 0:
work? Maybe there is no storage associated with pName, I don't know the wstring type.
According to the docs, GetModuleBaseNameW needs the rights PROCESS_QUERY_INFORMATION and PROCESS_VM_READ. Plus, as @araq mentionned, you should preallocate the string.
Assuming you use winim, this code should work (works on my machine™)
̀
proc test() =
var hNDL = OpenProcess(cast[DWORD](PROCESS_QUERY_INFORMATION or PROCESS_VM_READ), FALSE, cast[DWORD](PID))
defer: CloseHandle(hNDL)
var pName = newWString(260)
if GetModuleBaseNameW(hNDL, 0, pName, 260) == 0:
echo GetLastError()
else:
echo pName
when isMainModule:
test()
How the go version works (in particular the var pName uint16 followed by &pname bit) eludes me completely.