diff --git a/xlib/api/win32/d3d12/structs.py b/xlib/api/win32/d3d12/structs.py new file mode 100644 index 0000000..27e1d78 --- /dev/null +++ b/xlib/api/win32/d3d12/structs.py @@ -0,0 +1,40 @@ +from ctypes import c_uint, c_int, Structure + +class D3D_FEATURE_LEVEL(c_uint): + D3D_FEATURE_LEVEL_1_0_CORE = 0x1000 + D3D_FEATURE_LEVEL_9_1 = 0x9100 + D3D_FEATURE_LEVEL_9_2 = 0x9200 + D3D_FEATURE_LEVEL_9_3 = 0x9300 + D3D_FEATURE_LEVEL_10_0 = 0xa000 + D3D_FEATURE_LEVEL_10_1 = 0xa100 + D3D_FEATURE_LEVEL_11_0 = 0xb000 + D3D_FEATURE_LEVEL_11_1 = 0xb100 + D3D_FEATURE_LEVEL_12_0 = 0xc000 + D3D_FEATURE_LEVEL_12_1 = 0xc100 + +class D3D12_COMMAND_LIST_TYPE(c_uint): + D3D12_COMMAND_LIST_TYPE_DIRECT = 0 + D3D12_COMMAND_LIST_TYPE_BUNDLE = 1 + D3D12_COMMAND_LIST_TYPE_COMPUTE = 2 + D3D12_COMMAND_LIST_TYPE_COPY = 3 + D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE = 4 + D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS = 5 + D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE = 6 + +class D3D12_COMMAND_QUEUE_FLAGS(c_uint): + D3D12_COMMAND_QUEUE_FLAG_NONE = 0 + D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT = 0x1 + + +class D3D12_COMMAND_QUEUE_DESC(Structure): + _fields_ = [('Type', D3D12_COMMAND_LIST_TYPE), + ('Priority', c_int), + ('Flags', D3D12_COMMAND_QUEUE_FLAGS), + ('NodeMask', c_uint), + ] + + def __init__(self): + self.Type : D3D12_COMMAND_LIST_TYPE = D3D12_COMMAND_LIST_TYPE() + self.Priority : c_int = c_int() + self.Flags : D3D12_COMMAND_QUEUE_FLAGS = D3D12_COMMAND_QUEUE_FLAGS() + self.NodeMask : c_uint = c_uint() \ No newline at end of file diff --git a/xlib/api/win32/dshow/__init__.py b/xlib/api/win32/dshow/__init__.py new file mode 100644 index 0000000..72bec87 --- /dev/null +++ b/xlib/api/win32/dshow/__init__.py @@ -0,0 +1 @@ +from .helper import get_video_input_devices_names \ No newline at end of file diff --git a/xlib/api/win32/dshow/helper.py b/xlib/api/win32/dshow/helper.py new file mode 100644 index 0000000..6489213 --- /dev/null +++ b/xlib/api/win32/dshow/helper.py @@ -0,0 +1,40 @@ +from typing import List +from .. import ole32, uuids, strmif, wintypes, objidl, oaidl + + + +def get_video_input_devices_names() -> List[str]: + """ + returns a list of available names of VideoInputDevice's + + ole32 should be initialized before use + """ + # based on https://docs.microsoft.com/ru-ru/windows/win32/directshow/selecting-a-capture-device + + names = [] + sys_dev_enum = strmif.ICreateDevEnum() + if ole32.CoCreateInstance(uuids.CLSID_SystemDeviceEnum, None, ole32.CLSCTX.CLSCTX_INPROC_SERVER, strmif.ICreateDevEnum.IID, sys_dev_enum) == wintypes.ERROR.SUCCESS: + pEnumCat = objidl.IEnumMoniker() + + if sys_dev_enum.CreateClassEnumerator(uuids.CLSID_VideoInputDeviceCategory, pEnumCat, 0) == wintypes.ERROR.SUCCESS: + + moniker = objidl.IMoniker() + + while pEnumCat.Next(1, moniker, None) == wintypes.ERROR.SUCCESS: + + prop_bag = oaidl.IPropertyBag() + if moniker.BindToStorage(None, None, oaidl.IPropertyBag.IID, prop_bag) == wintypes.ERROR.SUCCESS: + var = wintypes.VARIANT() + + hr = prop_bag.Read(wintypes.LPCOLESTR('Description'), var, None ) + if hr != wintypes.ERROR.SUCCESS: + hr = prop_bag.Read(wintypes.LPCOLESTR('FriendlyName'), var, None ) + + names.append(var.value.bstrVal.value if hr == wintypes.ERROR.SUCCESS else 'unnamed') + + prop_bag.Release() + moniker.Release() + pEnumCat.Release() + sys_dev_enum.Release() + + return names \ No newline at end of file diff --git a/xlib/api/win32/dxgi/dxgi.py b/xlib/api/win32/dxgi/dxgi.py index bce0956..aec8457 100644 --- a/xlib/api/win32/dxgi/dxgi.py +++ b/xlib/api/win32/dxgi/dxgi.py @@ -1,13 +1,13 @@ -from ctypes import (POINTER, WINFUNCTYPE, byref, c_byte, c_int64, c_longlong, - c_size_t, c_ubyte, c_uint, c_uint32, c_ulong, c_void_p, - c_wchar) -from typing import List, Union +from ctypes import POINTER, c_longlong, c_uint, c_void_p +from typing import Union + from xlib.api.win32.wintypes.wintypes import BOOL -from ..wintypes import (ERROR, GUID, HRESULT, REFGUID, REFIID, IUnknown, dll_import, - interface) +from ..wintypes import (ERROR, GUID, HRESULT, REFGUID, REFIID, IUnknown, + dll_import, interface) from .structs import * + @interface class IDXGIObject(IUnknown): def SetPrivateData (self, guid : REFGUID, id : c_uint, data : c_void_p) -> HRESULT: ... @@ -118,4 +118,4 @@ def create_DXGIFactory4() -> Union[IDXGIFactory4, None]: result = IDXGIFactory4() if CreateDXGIFactory2(0, IDXGIFactory4.IID, result ) == ERROR.SUCCESS: return result - return None \ No newline at end of file + return None diff --git a/xlib/api/win32/kernel32/kernel32.py b/xlib/api/win32/kernel32/kernel32.py index 5d0b3c2..8f859c3 100644 --- a/xlib/api/win32/kernel32/kernel32.py +++ b/xlib/api/win32/kernel32/kernel32.py @@ -33,6 +33,6 @@ def SetPriorityClass(hProcess : HANDLE, priority_class : DWORD ) -> BOOL: ... def WaitForSingleObject(hHandle : HANDLE, dwMilliseconds : DWORD) -> DWORD:... @dll_import('kernel32') -def Sleep( dwMilliseconds : DWORD):... +def Sleep( dwMilliseconds : DWORD) -> None:... diff --git a/xlib/api/win32/oaidl/__init__.py b/xlib/api/win32/oaidl/__init__.py new file mode 100644 index 0000000..5169622 --- /dev/null +++ b/xlib/api/win32/oaidl/__init__.py @@ -0,0 +1 @@ +from .oaidl import IPropertyBag, IErrorLog \ No newline at end of file diff --git a/xlib/api/win32/oaidl/oaidl.py b/xlib/api/win32/oaidl/oaidl.py new file mode 100644 index 0000000..40d842d --- /dev/null +++ b/xlib/api/win32/oaidl/oaidl.py @@ -0,0 +1,14 @@ +from ctypes import POINTER, c_void_p, c_wchar_p +from ..wintypes import (GUID, DWORD, IUnknown, interface, VARIANT, HRESULT, LPCOLESTR) + + +@interface +class IErrorLog(IUnknown): + def AddError(self, pszPropName : LPCOLESTR, pExcepInfo : c_void_p) -> HRESULT: ... #EXCEPINFO + IID = GUID('3127ca40-446e-11ce-8135-00aa004bb851') + +@interface +class IPropertyBag(IUnknown): + def Read(self, pszPropName : LPCOLESTR, pVar : POINTER(VARIANT), pErrorLog : IErrorLog) -> HRESULT: ... + def Write(self, pszPropName : LPCOLESTR, pVar : POINTER(VARIANT)) -> HRESULT: ... + IID = GUID('55272a00-42cb-11ce-8135-00aa004bb851') diff --git a/xlib/api/win32/objidl/__init__.py b/xlib/api/win32/objidl/__init__.py new file mode 100644 index 0000000..34430bf --- /dev/null +++ b/xlib/api/win32/objidl/__init__.py @@ -0,0 +1 @@ +from .objidl import IEnumMoniker, IMoniker, IPersistStream, IPersist, IStream \ No newline at end of file diff --git a/xlib/api/win32/objidl/objidl.py b/xlib/api/win32/objidl/objidl.py new file mode 100644 index 0000000..128ba9f --- /dev/null +++ b/xlib/api/win32/objidl/objidl.py @@ -0,0 +1,107 @@ +from ctypes import POINTER, c_void_p +from ..wintypes import (GUID, DWORD, IUnknown, CLSID, interface, HRESULT, REFIID, BOOL, ULARGE_INTEGER) + +@interface +class IStream(IUnknown): #ISequentialStream + IID = GUID('0000000c-0000-0000-c000-000000000046') + + +@interface +class IPersist(IUnknown): + def GetClassID(self, pClassID : POINTER(CLSID) ) -> HRESULT: ... + IID = GUID('0000010c-0000-0000-c000-000000000046') + +@interface +class IPersistStream(IPersist): + def IsDirty(self) -> HRESULT: ... + def Load(self, pStm : IStream) -> HRESULT: ... + def Save(self, pStm : IStream, fClearDirty : BOOL) -> HRESULT: ... + def GetSizeMax(self, pcbSize : POINTER(ULARGE_INTEGER) ) -> HRESULT: ... + IID = GUID('00000109-0000-0000-c000-000000000046') + +@interface +class IMoniker(IPersistStream): + + def BindToObject(self, + pbc : c_void_p, #IBindCtx + pmkToLeft : IUnknown, #IMoniker, + riidResult : REFIID, + ppvResult : POINTER(c_void_p)) -> HRESULT: ... + + def BindToStorage(self, + pbc : c_void_p, #IBindCtx + pmkToLeft : IUnknown, #IMoniker, + riid : REFIID, + ppvObj : POINTER(c_void_p)) -> HRESULT: ... + + # virtual HRESULT STDMETHODCALLTYPE Reduce( + # IBindCtx *pbc, + # DWORD dwReduceHowFar, + # IMoniker **ppmkToLeft, + # IMoniker **ppmkReduced) = 0; + + # virtual HRESULT STDMETHODCALLTYPE ComposeWith( + # IMoniker *pmkRight, + # WINBOOL fOnlyIfNotGeneric, + # IMoniker **ppmkComposite) = 0; + + # virtual HRESULT STDMETHODCALLTYPE Enum( + # WINBOOL fForward, + # IEnumMoniker **ppenumMoniker) = 0; + + # virtual HRESULT STDMETHODCALLTYPE IsEqual( + # IMoniker *pmkOtherMoniker) = 0; + + # virtual HRESULT STDMETHODCALLTYPE Hash( + # DWORD *pdwHash) = 0; + + # virtual HRESULT STDMETHODCALLTYPE IsRunning( + # IBindCtx *pbc, + # IMoniker *pmkToLeft, + # IMoniker *pmkNewlyRunning) = 0; + + # virtual HRESULT STDMETHODCALLTYPE GetTimeOfLastChange( + # IBindCtx *pbc, + # IMoniker *pmkToLeft, + # FILETIME *pFileTime) = 0; + + # virtual HRESULT STDMETHODCALLTYPE Inverse( + # IMoniker **ppmk) = 0; + + # virtual HRESULT STDMETHODCALLTYPE CommonPrefixWith( + # IMoniker *pmkOther, + # IMoniker **ppmkPrefix) = 0; + + # virtual HRESULT STDMETHODCALLTYPE RelativePathTo( + # IMoniker *pmkOther, + # IMoniker **ppmkRelPath) = 0; + + # virtual HRESULT STDMETHODCALLTYPE GetDisplayName( + # IBindCtx *pbc, + # IMoniker *pmkToLeft, + # LPOLESTR *ppszDisplayName) = 0; + + # virtual HRESULT STDMETHODCALLTYPE ParseDisplayName( + # IBindCtx *pbc, + # IMoniker *pmkToLeft, + # LPOLESTR pszDisplayName, + # ULONG *pchEaten, + # IMoniker **ppmkOut) = 0; + + # virtual HRESULT STDMETHODCALLTYPE IsSystemMoniker( + # DWORD *pdwMksys) = 0; + + IID = GUID('0000000f-0000-0000-c000-000000000046') + + +@interface +class IEnumMoniker(IUnknown): + #def CreateClassEnumerator(refiid : REFIID, enumMoniker : POINTER(IEnumMoniker), flags : DWORD ) -> HRESULT: ... + + def Next(self, celt : DWORD, rgelt : POINTER(IMoniker), pceltFetched : POINTER(DWORD)) -> HRESULT: ... + + #virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt) = 0; + #virtual HRESULT STDMETHODCALLTYPE Reset() = 0; + #virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMoniker **ppenum) = 0; + + IID = GUID('00000102-0000-0000-C000-000000000046') diff --git a/xlib/api/win32/ole32/__init__.py b/xlib/api/win32/ole32/__init__.py new file mode 100644 index 0000000..d0d59d2 --- /dev/null +++ b/xlib/api/win32/ole32/__init__.py @@ -0,0 +1 @@ +from .ole32 import CoInitializeEx, COINIT, CLSCTX, CoCreateInstance, CoUninitialize \ No newline at end of file diff --git a/xlib/api/win32/ole32/ole32.py b/xlib/api/win32/ole32/ole32.py new file mode 100644 index 0000000..639272d --- /dev/null +++ b/xlib/api/win32/ole32/ole32.py @@ -0,0 +1,18 @@ +from ctypes import (POINTER, WINFUNCTYPE, byref, c_byte, c_int64, c_longlong, + c_size_t, c_ubyte, c_uint, c_uint32, c_ulong, c_void_p, + c_wchar) +from typing import Union + +from ..wintypes import (DWORD, ERROR, GUID, HRESULT, REFCLSID, REFGUID, REFIID, + IUnknown, dll_import, interface) +from .structs import * + + +@dll_import('ole32') +def CoInitializeEx(pvReserved : c_void_p, dwCoInit : COINIT ) -> HRESULT: ... + +@dll_import('ole32') +def CoUninitialize() -> None: ... + +@dll_import('ole32') +def CoCreateInstance (rclsid : REFCLSID, pUnkOuter : POINTER(IUnknown), dwClsContext : CLSCTX, refiid : REFIID, ppv : POINTER(IUnknown) ) -> HRESULT: ... diff --git a/xlib/api/win32/ole32/structs.py b/xlib/api/win32/ole32/structs.py new file mode 100644 index 0000000..ae13a79 --- /dev/null +++ b/xlib/api/win32/ole32/structs.py @@ -0,0 +1,36 @@ +from ..wintypes import DWORD + +class COINIT(DWORD): + APARTMENTTHREADED = 0x2 + MULTITHREADED = 0x2 + DISABLE_OLE1DDE = 0x4 + SPEED_OVER_MEMORY = 0x8 + +class CLSCTX(DWORD): + CLSCTX_INPROC_SERVER = 0x1 + CLSCTX_INPROC_HANDLER = 0x2 + CLSCTX_LOCAL_SERVER = 0x4 + CLSCTX_INPROC_SERVER16 = 0x8 + CLSCTX_REMOTE_SERVER = 0x10 + CLSCTX_INPROC_HANDLER16 = 0x20 + CLSCTX_RESERVED1 = 0x40 + CLSCTX_RESERVED2 = 0x80 + CLSCTX_RESERVED3 = 0x100 + CLSCTX_RESERVED4 = 0x200 + CLSCTX_NO_CODE_DOWNLOAD = 0x400 + CLSCTX_RESERVED5 = 0x800 + CLSCTX_NO_CUSTOM_MARSHAL = 0x1000 + CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000 + CLSCTX_NO_FAILURE_LOG = 0x4000 + CLSCTX_DISABLE_AAA = 0x8000 + CLSCTX_ENABLE_AAA = 0x10000 + CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000 + CLSCTX_ACTIVATE_X86_SERVER = 0x40000 + CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000 + CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000 + CLSCTX_ENABLE_CLOAKING = 0x100000 + CLSCTX_APPCONTAINER = 0x400000 + CLSCTX_ACTIVATE_AAA_AS_IU = 0x800000 + CLSCTX_RESERVED6 = 0x1000000 + CLSCTX_ACTIVATE_ARM32_SERVER = 0x2000000 + CLSCTX_PS_DLL = 0x8000000 \ No newline at end of file diff --git a/xlib/api/win32/oleaut32/__init__.py b/xlib/api/win32/oleaut32/__init__.py new file mode 100644 index 0000000..e5d8321 --- /dev/null +++ b/xlib/api/win32/oleaut32/__init__.py @@ -0,0 +1 @@ +from .oleaut32 import VariantInit \ No newline at end of file diff --git a/xlib/api/win32/oleaut32/oleaut32.py b/xlib/api/win32/oleaut32/oleaut32.py new file mode 100644 index 0000000..8a6266d --- /dev/null +++ b/xlib/api/win32/oleaut32/oleaut32.py @@ -0,0 +1,7 @@ +from ctypes import POINTER, Structure + +from ..wintypes import VARIANT, dll_import + + +@dll_import('OleAut32') +def VariantInit( pvarg : POINTER(VARIANT) ) -> None: ... diff --git a/xlib/api/win32/strmif/__init__.py b/xlib/api/win32/strmif/__init__.py new file mode 100644 index 0000000..ddb8daf --- /dev/null +++ b/xlib/api/win32/strmif/__init__.py @@ -0,0 +1 @@ +from .strmif import ICreateDevEnum \ No newline at end of file diff --git a/xlib/api/win32/strmif/strmif.py b/xlib/api/win32/strmif/strmif.py new file mode 100644 index 0000000..a718899 --- /dev/null +++ b/xlib/api/win32/strmif/strmif.py @@ -0,0 +1,10 @@ +from ctypes import POINTER + +from ..objidl import IEnumMoniker +from ..wintypes import DWORD, GUID, HRESULT, REFIID, IUnknown, interface + + +@interface +class ICreateDevEnum(IUnknown): + def CreateClassEnumerator(self, refiid : REFIID, enumMoniker : POINTER(IEnumMoniker), flags : DWORD ) -> HRESULT: ... + IID = GUID('29840822-5B84-11D0-BD3B-00A0C911CE86') diff --git a/xlib/api/win32/uuids/__init__.py b/xlib/api/win32/uuids/__init__.py new file mode 100644 index 0000000..6bdaef2 --- /dev/null +++ b/xlib/api/win32/uuids/__init__.py @@ -0,0 +1 @@ +from .uuids import CLSID_SystemDeviceEnum, CLSID_VideoInputDeviceCategory \ No newline at end of file diff --git a/xlib/api/win32/uuids/uuids.py b/xlib/api/win32/uuids/uuids.py new file mode 100644 index 0000000..c723a2f --- /dev/null +++ b/xlib/api/win32/uuids/uuids.py @@ -0,0 +1,4 @@ +from ..wintypes import CLSID + +CLSID_SystemDeviceEnum = CLSID('62BE5D10-60EB-11d0-BD3B-00A0C911CE86') +CLSID_VideoInputDeviceCategory = CLSID('860bb310-5d01-11d0-bd3b-00a0c911ce86') \ No newline at end of file diff --git a/xlib/api/win32/winmm/winmm.py b/xlib/api/win32/winmm/winmm.py index bc0a3a7..1c3091f 100644 --- a/xlib/api/win32/winmm/winmm.py +++ b/xlib/api/win32/winmm/winmm.py @@ -1,6 +1,4 @@ -#from ctypes import c_void_p, c_wchar_p, POINTER -from ..wintypes import BOOL, DWORD, MMRESULT, dll_import - +from ..wintypes import DWORD, MMRESULT, dll_import @dll_import('Winmm') def timeBeginPeriod(uPeriod : DWORD) -> MMRESULT: ... \ No newline at end of file diff --git a/xlib/api/win32/wintypes/__init__.py b/xlib/api/win32/wintypes/__init__.py index 91a1d47..e1e99e5 100644 --- a/xlib/api/win32/wintypes/__init__.py +++ b/xlib/api/win32/wintypes/__init__.py @@ -1,3 +1,6 @@ -from .wintypes import (BOOL, DWORD, ERROR, GUID, HANDLE, HRESULT, IID, - LARGE_INTEGER, MMERROR, MMRESULT, REFGUID, REFIID, - IUnknown, dll_import, interface) +from .wintypes import (BOOL, CHAR, CLSID, DOUBLE, DWORD, ERROR, FLOAT, GUID, + HANDLE, HRESULT, IID, INT, LARGE_INTEGER, LONG, + LONGLONG, LPCOLESTR, MMERROR, MMRESULT, PVOID, + REFCLSID, REFGUID, REFIID, SHORT, UINT, ULARGE_INTEGER, + USHORT, VARIANT, VARTYPE, WORD, IUnknown, dll_import, + interface) diff --git a/xlib/api/win32/wintypes/wintypes.py b/xlib/api/win32/wintypes/wintypes.py index 1752094..0a43b55 100644 --- a/xlib/api/win32/wintypes/wintypes.py +++ b/xlib/api/win32/wintypes/wintypes.py @@ -1,23 +1,28 @@ import ctypes import uuid -from ctypes import (POINTER, WINFUNCTYPE, byref, c_byte, c_int64, - c_longlong, c_size_t, c_ubyte, c_uint, c_uint32, c_ulong, - c_void_p, c_wchar) +from ctypes import (POINTER, WINFUNCTYPE, c_char_p, c_int16, c_int32, c_float, c_double, c_uint8, + c_int64, c_int8, c_size_t, c_ubyte, c_uint, c_uint16, + c_uint32, c_uint64, c_ulong, c_void_p, c_wchar_p) from ctypes.util import find_library from enum import IntEnum dlls_by_name = {} def dll_import(dll_name): + """ + + always annotate return type even if it is None ! + """ + dll = dlls_by_name.get(dll_name, None) if dll is None: try: dll = ctypes.cdll.LoadLibrary(find_library(dll_name)) except: pass - + dlls_by_name[dll_name] = dll - + def decorator(func): if dll is not None: dll_func = getattr(dll, func.__name__) @@ -26,9 +31,9 @@ def dll_import(dll_name): dll_func.restype = anno[-1] else: dll_func = None - + def wrapper(*args): - if dll_func is None: + if dll_func is None: raise RuntimeError(f'Unable to load {dll_name} library.') return dll_func(*args) return wrapper @@ -38,9 +43,9 @@ def dll_import(dll_name): def interface(cls_obj): """ Decorator for COM interfaces. - + First declarations must be a virtual functions. - + IID = GUID('') declares the end of virtual functions declarations """ virtual_idx = None @@ -54,30 +59,30 @@ def interface(cls_obj): break if virtual_idx is None: virtual_idx = 0 - + if 'IID' not in list(cls_obj.__dict__.keys()): raise Exception(f'class {cls_obj} declared as @interface, but no IID variable found.') - + for key, value in list(cls_obj.__dict__.items()): if len(key) >= 2 and key[0:2] == '__': continue if key == 'IID': break - + anno_list = list(value.__annotations__.values()) - + func_type = WINFUNCTYPE(anno_list[-1], c_void_p, *anno_list[:-1]) def wrapper(self, *args, _key=key, _virtual_idx=virtual_idx, _func_type=func_type): func = getattr(self, '_func_'+_key, None) if func is None: if self.value is None: raise Exception(f'{self} is not initialized.') - + vf_table = ctypes.cast( c_void_p( ctypes.cast(self, POINTER(c_void_p))[0] ), POINTER(c_void_p)) func = _func_type(vf_table[_virtual_idx]) setattr(self, '_func_'+key, func) return func(self, *args) - + setattr(cls_obj, key, wrapper) virtual_idx += 1 @@ -88,19 +93,20 @@ def interface(cls_obj): class ERROR(IntEnum): # https://raw.githubusercontent.com/tpn/winsdk-10/master/Include/10.0.14393.0/shared/winerror.h SUCCESS = 0 + INVALID_FUNCTION = 1 E_NOINTERFACE = 0x80004002 - + DXGI_ERROR_NOT_FOUND = 0x887A0002 - + class MMERROR(IntEnum): # http://pinvoke.net/default.aspx/winmm/MMRESULT.html - NOERROR = 0 + NOERROR = 0 ERROR = 1 -class MMRESULT(c_ulong): +class MMRESULT(c_ulong): def __eq__(self, other): if isinstance(other, int): - return self.value == other + return self.value == other elif isinstance(other, self.__class__): return self.value == other.value else: @@ -116,11 +122,11 @@ class MMRESULT(c_ulong): return f'MMRESULT ({self.value})' def __repr__(self): return self.__str__() - -class HRESULT(c_ulong): + +class HRESULT(c_ulong): def __eq__(self, other): if isinstance(other, int): - return self.value == other + return self.value == other elif isinstance(other, self.__class__): return self.value == other.value else: @@ -136,8 +142,8 @@ class HRESULT(c_ulong): return f'HRESULT ({self.value})' def __repr__(self): return self.__str__() - -class HANDLE(c_void_p): + +class HANDLE(c_void_p): def __eq__(self, other): if isinstance(other, self.__class__): return self.value == other.value @@ -151,38 +157,9 @@ class HANDLE(c_void_p): return f'HANDLE ({self.value})' def __repr__(self): return self.__str__() - -class DWORD(c_uint): - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.value == other.value - else: - return False - def __ne__(self, other): - return not(self == other) - def __hash__(self): - return self.value.__hash__() - def __str__(self): - return f'DWORD ({self.value})' - def __repr__(self): - return self.__str__() -class LARGE_INTEGER(c_int64): - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.value == other.value - else: - return False - def __ne__(self, other): - return not(self == other) - def __hash__(self): - return self.value.__hash__() - def __str__(self): - return f'LARGE_INTEGER ({self.value})' - def __repr__(self): - return self.__str__() - -class BOOL(c_size_t): + +class BOOL(c_size_t): def __eq__(self, other): if isinstance(other, self.__class__): return (self.value != 0) == (other.value != 0) @@ -197,19 +174,282 @@ class BOOL(c_size_t): def __str__(self): return f'BOOL ({self.value != 0})' def __repr__(self): - return self.__str__() - - + return self.__str__() + +class CHAR(c_int8): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'CHAR ({self.value})' + def __repr__(self): + return self.__str__() + +class BYTE(c_uint8): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'BYTE ({self.value})' + def __repr__(self): + return self.__str__() + +class SHORT(c_int16): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'SHORT ({self.value})' + def __repr__(self): + return self.__str__() + +class USHORT(c_uint16): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'USHORT ({self.value})' + def __repr__(self): + return self.__str__() + +class LONG(c_int32): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'LONG ({self.value})' + def __repr__(self): + return self.__str__() + +class ULONG(c_uint32): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'ULONG ({self.value})' + def __repr__(self): + return self.__str__() + +class INT(c_int32): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'INT ({self.value})' + def __repr__(self): + return self.__str__() + +class UINT(c_uint32): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'UINT ({self.value})' + def __repr__(self): + return self.__str__() + +class WORD(c_uint16): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'WORD ({self.value})' + def __repr__(self): + return self.__str__() + +class DWORD(c_uint): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'DWORD ({self.value})' + def __repr__(self): + return self.__str__() + +class LARGE_INTEGER(c_int64): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'LARGE_INTEGER ({self.value})' + def __repr__(self): + return self.__str__() + +class LONGLONG(c_int64): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'LONGLONG ({self.value})' + def __repr__(self): + return self.__str__() + +class ULONGLONG(c_uint64): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'ULONGLONG ({self.value})' + def __repr__(self): + return self.__str__() + +class ULARGE_INTEGER(c_uint64): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'ULARGE_INTEGER ({self.value})' + def __repr__(self): + return self.__str__() + +class FLOAT(c_float): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'FLOAT ({self.value})' + def __repr__(self): + return self.__str__() + +class DOUBLE(c_double): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'DOUBLE ({self.value})' + def __repr__(self): + return self.__str__() + +class PVOID(c_void_p): + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + else: + return False + def __ne__(self, other): + return not(self == other) + def __hash__(self): + return self.value.__hash__() + def __str__(self): + return f'PVOID ({self.value})' + def __repr__(self): + return self.__str__() + class GUID (ctypes.Structure): _fields_ = [('data', c_ubyte * 16)] def __init__(self, hexstr=None): super().__init__() self.data[:] = uuid.UUID(hexstr).bytes_le + +class CSTR(c_char_p): + def __init__(self, s : str): + super().__init__(s.encode('utf-8')) + +class CLSID(GUID): ... +class LPCOLESTR(c_wchar_p): ... +class BSTR(c_wchar_p): ... + IID = GUID REFIID = POINTER(IID) REFGUID = POINTER(GUID) - - +REFCLSID = POINTER(CLSID) +#LPOLESTR = POINTER(OLESTR) @interface class IUnknown(c_void_p): @@ -226,126 +466,136 @@ class IUnknown(c_void_p): return None -# class COMObject(c_void_p): -# """ -# base class for COM objects - -# you should implement _vf_table in every subclass -# """ -# def _vf_table(): return dict() - -# def _get_vf_func(self, name): -# """ -# returns function from vf table by name -# """ -# if self.value is None: -# raise Exception(f'COMObject {self} was not assigned.') - -# vf_proto_cls = self.__class__ - -# vf = getattr(vf_proto_cls, '_vf', None) -# if vf is None: -# vf = {} - -# hierarchy = [] -# while vf_proto_cls != COMObject: -# hierarchy.insert(0, vf_proto_cls) -# vf_proto_cls = vf_proto_cls.__bases__[0] - -# func_id = 0 -# for vf_proto_cls in hierarchy: -# for func_name, func_type in vf_proto_cls._vf_table().items(): -# if func_name in vf: -# raise Exception(f'Function duplicate {func_name} in {self}') -# vf[func_name] = (func_id, func_type) -# func_id += 1 -# setattr(vf_proto_cls, '_vf', vf) - -# func_id, func_type = vf[name] -# vf_table = ct.cast( c_void_p( ct.cast(self, POINTER(c_void_p))[0] ), POINTER(c_void_p)) -# return func_type(vf_table[func_id]) +class VARTYPE(SHORT): + VT_EMPTY = 0 + VT_NULL = 1 + VT_I2 = 2 + VT_I4 = 3 + VT_R4 = 4 + VT_R8 = 5 + VT_CY = 6 + VT_DATE = 7 + VT_BSTR = 8 + VT_DISPATCH = 9 + VT_ERROR = 10 + VT_BOOL = 11 + VT_VARIANT = 12 + VT_UNKNOWN = 13 + VT_DECIMAL = 14 + VT_I1 = 16 + VT_UI1 = 17 + VT_UI2 = 18 + VT_UI4 = 19 + VT_I8 = 20 + VT_UI8 = 21 + VT_INT = 22 + VT_UINT = 23 + VT_VOID = 24 + VT_HRESULT = 25 + VT_PTR = 26 + VT_SAFEARRAY = 27 + VT_CARRAY = 28 + VT_USERDEFINED = 29 + VT_LPSTR = 30 + VT_LPWSTR = 31 + VT_RECORD = 36 + VT_INT_PTR = 37 + VT_UINT_PTR = 38 + VT_FILETIME = 64 + VT_BLOB = 65 + VT_STREAM = 66 + VT_STORAGE = 67 + VT_STREAMED_OBJECT = 68 + VT_STORED_OBJECT = 69 + VT_BLOB_OBJECT = 70 + VT_CF = 71 + VT_CLSID = 72 + VT_VERSIONED_STREAM = 73 + VT_BSTR_BLOB = 0xfff + VT_VECTOR = 0x1000 + VT_ARRAY = 0x2000 + VT_BYREF = 0x4000 + VT_RESERVED = 0x8000 + VT_ILLEGAL = 0xffff + VT_ILLEGALMASKED = 0xfff + VT_TYPEMASK = 0xff -# class IUnknown(COMObject): -# def QueryInterface(self, iid : REFIID, out_IUnknown : POINTER(c_void_p)) -> HRESULT: -# return self._get_vf_func('QueryInterface')(self, iid, out_IUnknown) - -# def AddRef(self) -> c_ulong: -# return self._get_vf_func('AddRef')(self) - -# def Release(self) -> c_ulong: -# return self._get_vf_func('Release')(self) - -# IID = GUID('00000000-0000-0000-C000-000000000046') - -# def _vf_table(): return dict( -# QueryInterface = WINFUNCTYPE(HRESULT, IUnknown, REFIID, POINTER(IUnknown) ), -# AddRef = WINFUNCTYPE(c_ulong, IUnknown), -# Release = WINFUNCTYPE(c_ulong, IUnknown), -# ) - +class _VARIANT_RECORD(ctypes.Structure): + _fields_ = [ ('pvRecord', PVOID), + ('pRecInfo', IUnknown ) ] #IRecordInfo -# def query_interface(self, iid : IID) -> 'IUnknown': -# out_IUnknown = IUnknown() -# hr = self.QueryInterface(iid, out_IUnknown) -# if hr == ERROR.SUCCESS: -# return out_IUnknown -# return None - - -# class COMBase(c_void_p): ... - +class _VARIANT_NAME_3(ctypes.Union): + _fields_ = [ ('llVal', LONGLONG), + ('lVal', LONG), + ('bVal', BYTE), + ('iVal', SHORT), + ('fltVal', FLOAT), + ('dblVal', DOUBLE), + #VARIANT_BOOL boolVal; + #VARIANT_BOOL __OBSOLETE__VARIANT_BOOL; + #SCODE scode; + #CY cyVal; + #DATE date; + ('bstrVal', BSTR), + ('punkVal', IUnknown), + #IDispatch *pdispVal; + #SAFEARRAY *parray; + ('pbVal', POINTER(BYTE)), + ('piVal', POINTER(SHORT)), + ('plVal', POINTER(LONG)), + ('pllVal', POINTER(LONGLONG)), + ('pfltVal', POINTER(FLOAT)), + ('pdblVal', POINTER(DOUBLE)), + # VARIANT_BOOL *pboolVal; + # VARIANT_BOOL *__OBSOLETE__VARIANT_PBOOL; + # SCODE *pscode; + # CY *pcyVal; + # DATE *pdate; + ('pbstrVal', POINTER(BSTR) ), + ('ppunkVal', POINTER(IUnknown) ), + # IDispatch **ppdispVal; + # SAFEARRAY **pparray; + # VARIANT *pvarVal; + ('byref', PVOID), + ('cVal', CHAR), + ('uiVal', USHORT), + ('ulVal', ULONG), + ('ullVal', ULONGLONG), + ('intVal', INT), + ('uintVal', UINT), + #DECIMAL *pdecVal; + ('pcVal', POINTER(CHAR)), + ('puiVal', POINTER(USHORT)), + ('pulVal', POINTER(ULONG)), + ('pullVal', POINTER(ULONGLONG)), + ('pintVal', POINTER(INT)), + ('puintVal', POINTER(UINT)), -# def com_class(cls_obj): -# virtual_idx = 0 - -# # Determine virtuals count from parent class -# parent = cls_obj.__bases__[0] -# if parent != COMBase: -# virtual_idx = parent._virtuals_count - -# # Walk through all virtuals and assign virtual idx -# for key, value in cls_obj.__dict__.items(): -# _virtual_idx = getattr(value, '_virtual_idx', None) -# if _virtual_idx is not None: -# value._virtual_idx = virtual_idx -# virtual_idx += 1 - -# cls_obj._virtuals_count = virtual_idx -# return cls_obj - + ('record', _VARIANT_RECORD ), + ] + +class VARIANT(ctypes.Structure): + _fields_ = [('vt', VARTYPE ), + ('wReserved1', WORD), + ('wReserved2', WORD), + ('wReserved3', WORD), + ('value', _VARIANT_NAME_3), + ] + def __init__(self): + """ + by default initialized to VT_EMPTY + """ + + self.vt : VARTYPE = VARTYPE.VT_EMPTY + #self.wReserved1 : WORD = WORD() + #self.wReserved2 : WORD = WORD() + #self.wReserved3 : WORD = WORD() + #self.value : _VARIANT_NAME_3 = _VARIANT_NAME_3() + super().__init__() + + def __repr__(self): return self.__str__() + def __str__(self): + return f'VARIANT object: { self.vt }' -# @com_class -# class IUnknown(COMBase): -# @virtual -# def QueryInterface(self, refiid : REFIID, pIUnknown : POINTER(c_void_p) ) -> HRESULT: ... - -# @virtual -# def AddRef(self : COMBase) -> c_ulong: ... - -# @virtual -# def Release(self : COMBase) -> c_ulong: ... -# def virtual(func): -# func_type = None - -# def wrapper(this, *args): -# if wrapper._functype is None: -# x = wrapper._virtual_idx -# anno = list(func.__annotations__.values()) -# wrapper._functype = WINFUNCTYPE(anno[-1], *anno[:-1]) - -# vf_table = ct.cast( c_void_p( ct.cast(this, POINTER(c_void_p))[0] ), POINTER(c_void_p)) -# real_func = wrapper._functype( vf_table[wrapper._virtual_idx] ) - - -# import code -# code.interact(local=dict(globals(), **locals())) - - - -# return real_func(this, *args) -# wrapper._func = func -# wrapper._functype = None -# wrapper._virtual_idx = -1 -# return wrapper