Я пытаюсь реализовать недокументированную функцию NtCreateNamedPipeFile из NTAPI с ctypes, но я не могу заставить ее работать (у меня очень мало опыта работы с ctypes).
Во-первых,если я предоставляю все аргументы из определения функции, я получаю ошибку «ValueError: Процедура, вероятно, вызвана со слишком большим количеством аргументов (4 байта больше)».
Если я удаляю аргумент NamedPipeFileHandle (при условиичто дескриптор может быть тем, что возвращает эта функция), я получаю «OSError: [WinError 87] Параметр неверен».
Я пытался настроить типы и аргументы в моей реализации, но независимо от того, что я делаю,Я получаю тот же WinError 87. Он не очень описательный, поэтому трудно понять, что я здесь делаю неправильно (возможно, многие вещи).
Вот определения:
ULONG_PTR = ctypes.wintypes.WPARAM
FILE_READ_DATA = 0x00000001
FILE_WRITE_DATA = 0x00000002
SYNCHRONIZE = 0x00100000
FILE_READ_ATTRIBUTES = 0x80
FILE_CREATE = 0x00000002
def NtError(status):
err = ntdll.RtlNtStatusToDosError(status)
return ctypes.WinError(err)
class IO_STATUS_BLOCK(ctypes.Structure):
class _STATUS(ctypes.Union):
_fields_ = (('Status', LONG),
('Pointer', LPVOID))
_anonymous_ = '_Status',
_fields_ = (('_Status', _STATUS),
('Information', ULONG_PTR))
class UNICODE_STRING(ctypes.Structure):
_fields_ = (('Length', USHORT),
('MaximumLength', USHORT),
('Buffer', LPWSTR))
class OBJECT_ATTRIBUTES(ctypes.Structure):
_fields_ = (
('Length', ULONG),
('RootDirectory', HANDLE),
('ObjectName', UNICODE_STRING),
('Attributes', ULONG),
)
ntdll = ctypes.WinDLL('ntdll')
def _decl(name, ret=None, args=()):
fn = getattr(ntdll, name)
fn.restype = ret
fn.argtypes = args
return fn
NtCreateNamedPipeFile = _decl('NtCreateNamedPipeFile', LONG,
(
POINTER(HANDLE),
DWORD,
POINTER(OBJECT_ATTRIBUTES),
POINTER(IO_STATUS_BLOCK),
ULONG,
ULONG,
ULONG,
BOOL,
BOOL,
BOOL,
ULONG,
ULONG,
ULONG,
LARGE_INTEGER))
И сам звонок:
handle = HANDLE()
iosb = IO_STATUS_BLOCK()
us_pipe_name = UNICODE_STRING()
us_pipe_name.Buffer = '\\??\\pipe\\' + name
us_pipe_name.Length = len(us_pipe_name.Buffer)
us_pipe_name.MaximumLength = len(us_pipe_name.Buffer)
obj_attrs = OBJECT_ATTRIBUTES()
obj_attrs.ObjectName = us_pipe_name
status = NtCreateNamedPipeFile(
# ctypes.byref(handle), # NamedPipeFileHandle
FILE_READ_DATA | SYNCHRONIZE, # DesiredAccess
ctypes.byref(obj_attrs), # ObjectAttributes
ctypes.byref(iosb), # IoStatusBlock
0, # ShareAccess
FILE_CREATE, # CreateDisposition
0, # CreateOptions
0, # WriteModeMessage
0, # ReadModeMessage
1, # NonBlocking
1, # MaxInstances
1024, # InBufferSize
1024, # OutBufferSize
0, # DefaultTimeout
)
if status != 0:
exception = NtError(status)
raise exception
Что я тут не так делаю?