0

I am trying to use NetUserGetInfo in python using ctypes.

The function looks like the following as per documentation:

NET_API_STATUS NET_API_FUNCTION NetUserGetInfo(
 LPCWSTR servername,
 LPCWSTR username,
 DWORD level,
 LPBYTE *bufptr
);

I'm finding difficulty in calling the 4th argument to the function which is of type LPBYTE *bufptr

my code looks like following:

import ctypes
from ctypes.wintypes import LPWSTR
netap = ctypes.WinDLL("Netapi32.dll")
servername = None
username = ctypes.c_wchar_p("myuser")
bufptr = ctypes.POINTER(ctypes.c_byte)
class USER_INFO_0(ctypes.Structure):
 _fields_ = [
 ("usri0_name", LPWSTR)
 ]
usrio_name = username.bytes.decode()
level = USER_INFO_0()
response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
print(response)

Getting the following error:

Traceback (most recent call last):
 File ".\netusertest.py", line 17, in <module>
 response = netap.NetUserGetInfo(ctypes.byref(servername),ctypes.byref(username),level,ctypes.byref(bufptr))
TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCPointerType'

Any pointers are appreciated, I'm a beginner needless to say!

asked Jun 17, 2021 at 12:24

1 Answer 1

1

This line:

bufptr = ctypes.POINTER(ctypes.c_byte)

is a type declaration, not an instance, as your error points out, so it can't be taken by reference. Call the type to create an instance (ctypes.POINTER(ctypes.c_byte))()) but I recommend using appropriate wintypes instead.

I noticed you are trying to initialize a USER_INFO_0 instance. This is allocated and returned by the API and must be freed as well. level represent the type that will be returned as it can vary.

servername and username parameters can be passed as Unicode strings directly.

It also helps to define .argtypes and .restype to inform ctypes of the argument types and return type. Don't make ctypes guess. If defined correctly ctypes will report errors if you pass a type that can't be converted to the definition.

Here is code tested on 32- and 64-bit Python with an appropriate server/user:

import ctypes as ct
from ctypes import wintypes as w
# from lm.h headers.
NET_API_STATUS = w.DWORD
NERR_Success = 0
class USER_INFO_0(ct.Structure):
 _fields_ = [('usri0_name', w.LPWSTR)]
# WinDLL is appropriate as NET_API_FUNCTION is defined as __stdcall.
# This matters if the code runs under 32-bit Python.
netap = ct.WinDLL('netapi32')
netap.NetUserGetInfo.argtypes = w.LPCWSTR, w.LPCWSTR, w.DWORD, ct.POINTER(w.LPBYTE)
netap.NetUserGetInfo.restype = NET_API_STATUS
netap.NetApiBufferFree.argtypes = w.LPVOID,
netap.NetApiBufferFree.restype = NET_API_STATUS
bufptr = w.LPBYTE() # make an LPBYTE instance to hold the output parameter.
level = 0
response = netap.NetUserGetInfo('server', 'account', level, ct.byref(bufptr))
if response == NERR_Success:
 data = ct.cast(bufptr,ct.POINTER(USER_INFO_0)) # cast as indicated by level
 print(data.contents.usri0_name) # dereference pointer and access member
 netap.NetApiBufferFree(bufptr) # free the pointer
print(response)
answered Jun 17, 2021 at 18:29
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.