ctypes generation : added bitfield parsing/generation + update/fix some definitions

This commit is contained in:
hakril
2018-05-12 00:16:45 +02:00
parent 05e7b755b0
commit 11e4afeef5
12 changed files with 116 additions and 46 deletions
+2 -2
View File
@@ -77,7 +77,7 @@ class WinComParser(Parser):
args.append(self.parse_argument())
#print("Pass <{0}>".format(p))
self.next_token()
self.assert_token_type(ColonToken)
self.assert_token_type(SemiColonToken)
return ret_type.value, method_name.value, args
def parse(self):
@@ -113,7 +113,7 @@ class WinComParser(Parser):
self.next_token()
self.assert_token_type(StarToken)
typedefptr = self.assert_token_type(NameToken).value
self.assert_token_type(ColonToken)
self.assert_token_type(SemiColonToken)
res.typedefptr = typedefptr
return res
@@ -1,25 +1,25 @@
typedef struct ICallFrameWalkerVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ICallFrameWalker * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ICallFrameWalker * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ICallFrameWalker * This);
HRESULT ( STDMETHODCALLTYPE *OnWalkInterface )(
ICallFrameWalker * This,
/* [in] */ REFIID iid,
/* [in] */ PVOID *ppvInterface,
/* [in] */ BOOL fIn,
/* [in] */ BOOL fOut);
END_INTERFACE
} ICallFrameWalkerVtbl;
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ICallFrameWalker * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ICallFrameWalker * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ICallFrameWalker * This);
HRESULT ( STDMETHODCALLTYPE *OnWalkInterface )(
ICallFrameWalker * This,
/* [in] */ REFIID iid,
/* [in] */ PVOID *ppvInterface,
/* [in] */ BOOL fIn,
/* [in] */ BOOL fOut);
END_INTERFACE
} ICallFrameWalkerVtbl;
@@ -13,3 +13,13 @@ class COMInterface(ctypes.c_void_p):
return functools.partial(self._functions_[name], self)
return super(COMInterface, self).__getattribute__(name)
def __repr__(self):
description = "<NULL>" if not self.value else ""
return "<{0}{1} at {2:#x}>".format(type(self).__name__, description, id(self))
# Simplified API for QueryInterface for interface embeding there IID
def query(self, interfacetype):
interface = interfacetype()
self.QueryInterface(interface.IID, interface)
return interface
@@ -796,6 +796,7 @@
#define PERSIST_E_SIZEINDEFINITE (0x800B000AL)
#define PERSIST_E_NOTSELFSIZING (0x800B000BL)
#define TRUST_E_NOSIGNATURE (0x800B0100L)
#define TRUST_E_BAD_DIGEST (0x80096010L)
#define CERT_E_EXPIRED (0x800B0101L)
#define CERT_E_VALIDITYPERIODNESTING (0x800B0102L)
#define CERT_E_PURPOSE (0x800B0106L)
@@ -1677,3 +1677,27 @@ NTSTATUS WINAPI ApiSetResolveToHost (
_Out_ PBOOLEAN Resolved,
_Out_ PUNICODE_STRING HostBinary
);
VOID WINAPI Sleep(
_In_ DWORD dwMilliseconds
);
DWORD WINAPI SleepEx(
_In_ DWORD dwMilliseconds,
_In_ BOOL bAlertable
);
BOOL WINAPI GetProcessMitigationPolicy(
_In_ HANDLE hProcess,
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_Out_ PVOID lpBuffer,
_In_ SIZE_T dwLength
);
BOOL WINAPI SetProcessMitigationPolicy(
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_In_ PVOID lpBuffer,
_In_ SIZE_T dwLength
);
@@ -30,6 +30,7 @@ OLECHAR = c_wchar
POLECHAR = c_wchar_p
PUCHAR = POINTER(UCHAR)
double = c_double
DATE = double
PSID = PVOID
ULONGLONG = c_ulonglong
LONGLONG = c_longlong
@@ -76,4 +76,10 @@ typedef enum tagMSHLFLAGS {
MSHLFLAGS_TABLESTRONG = 1,
MSHLFLAGS_TABLEWEAK = 2,
MSHLFLAGS_NOPING = 4
} MSHLFLAGS;
} MSHLFLAGS;
typedef enum tagCALLFRAME_WALK {
CALLFRAME_WALK_IN = 1,
CALLFRAME_WALK_INOUT = 2,
CALLFRAME_WALK_OUT = 4
} CALLFRAME_WALK;
@@ -3039,7 +3039,7 @@ typedef struct _SYSTEMTIME {
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
typedef struct _CERT_EXTENSIONS {
+1 -1
View File
@@ -100,7 +100,7 @@ class WinFuncParser(Parser):
params.append(self.parse_func_arg(has_winapi))
self.assert_token_type(CloseParenthesisToken)
self.assert_token_type(ColonToken)
self.assert_token_type(SemiColonToken)
return WinFunc(return_type, func_name, params)
def parse(self):
+7 -2
View File
@@ -24,6 +24,10 @@ class NameToken(Token):
pass
class ColonToken(NoValueToken):
value = ":"
pass
class SemiColonToken(NoValueToken):
value = ";"
pass
@@ -73,8 +77,9 @@ class Lexer(object):
keywords = ["typedef", "struct", "enum", "union", "const"]
token_chr = {"*" : StarToken, "[" : OpenSquareBracketToken, "]" : CloseSquareBracketToken,
"{" : OpenBracketToken, "}" : CloseBracketToken, ";" : ColonToken,
"," : CommaToken, "(" : OpenParenthesisToken, ")" : CloseParenthesisToken, "#" : SharpToken, "=" : EqualToken}
"{" : OpenBracketToken, "}" : CloseBracketToken, ";" : SemiColonToken,
"," : CommaToken, "(" : OpenParenthesisToken, ")" : CloseParenthesisToken, "#" : SharpToken, "=" : EqualToken,
":": ColonToken}
def __init__(self, code, newlinetoken=False):
self.code = code
+22 -13
View File
@@ -1,18 +1,27 @@
import dummy_wintypes
import itertools
from winstruct import WinStruct, WinUnion, WinStructType, Ptr, WinEnum
from winstruct import WinStruct, WinUnion, WinStructType, Ptr, WinEnum, BitFieldValue
from simpleparser import *
class WinStructParser(Parser):
def __init__(self, *args, **kwargs):
super(WinStructParser, self).__init__(*args, **kwargs)
self.pack = None
def parse_array(self, ):
self.assert_token_type(OpenSquareBracketToken)
number = self.assert_token_type(NameToken).value
self.assert_token_type(CloseSquareBracketToken)
return number
def parse_array_or_bitfield(self):
if type(self.peek()) == OpenSquareBracketToken:
# Array
self.assert_token_type(OpenSquareBracketToken)
number = self.assert_token_type(NameToken).value
self.assert_token_type(CloseSquareBracketToken)
return number
# Bitfield
self.assert_token_type(ColonToken)
nb_bits = self.promote_to_int(self.next_token())
return BitFieldValue(nb_bits)
def parse_def(self):
if self.peek() == KeywordToken("struct"):
@@ -26,16 +35,16 @@ class WinStructParser(Parser):
def_name = self.assert_token_type(NameToken)
if type(self.peek()) == ColonToken:
if type(self.peek()) == SemiColonToken:
self.next_token()
return (def_type, def_name, 1)
number_rep = self.parse_array()
self.assert_token_type(ColonToken)
number_rep = self.parse_array_or_bitfield()
self.assert_token_type(SemiColonToken)
return (def_type, def_name, number_rep)
def parse_typedef(self, struct):
if type(self.peek()) == ColonToken: # Just a ; no typedef
if type(self.peek()) == SemiColonToken: # Just a ; no typedef
self.next_token()
return
sep = CommaToken()
@@ -50,7 +59,7 @@ class WinStructParser(Parser):
name = self.assert_token_type(NameToken)
add_to_typedef(name.value)
sep = self.next_token()
self.assert_token_type(ColonToken, sep)
self.assert_token_type(SemiColonToken, sep)
def parse_enum(self, is_typedef):
"""Handle enum typedef with no value assignement and 1 typedef after"""
@@ -87,7 +96,7 @@ class WinStructParser(Parser):
self.parse_typedef(res_enum)
#other_name = self.assert_token_type(NameToken).value
#res_enum.add_typedef(other_name)
#self.assert_token_type(ColonToken)
#self.assert_token_type(SemiColonToken)
return res_enum
@@ -126,7 +135,7 @@ class WinStructParser(Parser):
if is_typedef:
self.parse_typedef(result)
else:
self.assert_token_type(ColonToken)
self.assert_token_type(SemiColonToken)
return result
def parse(self):
+16 -2
View File
@@ -4,6 +4,15 @@ import collections
#Ptr = collections.namedtuple('Ptr', [''])
class BitFieldValue(object):
def __init__(self, nb_bits):
assert isinstance(nb_bits, int)
self.nb_bits = nb_bits
def __int__(self):
return self.nb_bits
class WinStructType(object):
def __init__(self, name):
self.name = name
@@ -70,7 +79,9 @@ class WinStruct(object):
res += ["{0}._pack_ = ".format(self.pack)]
res += ["{0}._fields_ = [".format(self.name)]
for (ftype, name, nb_rep) in self.fields:
if nb_rep == 1:
if isinstance(nb_rep, BitFieldValue):
res += [' ("{0}", {1}, {2}),'.format(name, ftype.generate_ctypes(), nb_rep.nb_bits)]
elif nb_rep == 1:
res+= [' ("{0}", {1}),'.format(name, ftype.generate_ctypes())]
else:
res+= [' ("{0}", {1} * {2}),'.format(name, ftype.generate_ctypes(), nb_rep)]
@@ -96,7 +107,10 @@ class WinStruct(object):
for (ftype, name, nb_rep) in self.fields:
if nb_rep == 1:
if isinstance(nb_rep, BitFieldValue):
# Should I check 'ftype' somewhere when we have a bitfield ?
res+= ' ("{0}", {1}, {2}),\n'.format(name, ftype.generate_ctypes(), nb_rep.nb_bits)
elif nb_rep == 1:
res+= ' ("{0}", {1}),\n'.format(name, ftype.generate_ctypes())
else:
res+= ' ("{0}", {1} * {2}),\n'.format(name, ftype.generate_ctypes(), nb_rep)