# XXX Should convert from STDMETHOD to COMMETHOD.

# generated by 'xml2py'
# flags '..\tools\windows.xml -m comtypes -m comtypes.automation -w -r .*TypeLibEx -r .*TypeLib -o typeinfo.py'
# then hacked manually
import ctypes
import sys
import weakref
from collections.abc import Callable, Sequence
from ctypes import (
    HRESULT,
    POINTER,
    OleDLL,
    WinDLL,
    byref,
    c_int,
    c_void_p,
    c_wchar_p,
    create_unicode_buffer,
)
from ctypes.wintypes import (
    DWORD,
    HMODULE,
    INT,
    LONG,
    LPWSTR,
    SHORT,
    UINT,
    ULONG,
    USHORT,
    WCHAR,
    WORD,
)
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, overload
from typing import Union as _UnionT

from comtypes import BSTR, COMMETHOD, GUID, IID, STDMETHOD, IUnknown, _CData
from comtypes._memberspec import PARAMFLAG_FHASCUSTDATA as PARAMFLAG_FHASCUSTDATA
from comtypes._memberspec import PARAMFLAG_FHASDEFAULT as PARAMFLAG_FHASDEFAULT
from comtypes._memberspec import PARAMFLAG_FIN as PARAMFLAG_FIN
from comtypes._memberspec import PARAMFLAG_FLCID as PARAMFLAG_FLCID
from comtypes._memberspec import PARAMFLAG_FOPT as PARAMFLAG_FOPT
from comtypes._memberspec import PARAMFLAG_FOUT as PARAMFLAG_FOUT
from comtypes._memberspec import PARAMFLAG_FRETVAL as PARAMFLAG_FRETVAL
from comtypes._memberspec import PARAMFLAG_NONE as PARAMFLAG_NONE
from comtypes.automation import (
    DISPID,
    DISPPARAMS,
    EXCEPINFO,
    LCID,
    SCODE,
    VARIANT,
    VARIANTARG,
    VARTYPE,
)

if TYPE_CHECKING:
    from ctypes import _Pointer

    from comtypes import hints  # type: ignore


_CT = TypeVar("_CT", bound=_CData)
_T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)

is_64_bit = sys.maxsize > 2**32

BOOL = c_int
HREFTYPE = DWORD
MEMBERID = DISPID
OLECHAR = WCHAR
PVOID = c_void_p
# See https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx#ULONG_PTR  # noqa
ULONG_PTR = ctypes.c_uint64 if is_64_bit else ctypes.c_ulong

LPOLESTR = POINTER(OLECHAR)
LPCOLESTR = c_wchar_p

################################################################
# enums
tagSYSKIND = c_int  # enum
SYS_WIN16 = 0
SYS_WIN32 = 1
SYS_MAC = 2
SYS_WIN64 = 3
SYSKIND = tagSYSKIND

tagREGKIND = c_int  # enum
REGKIND_DEFAULT = 0
REGKIND_REGISTER = 1
REGKIND_NONE = 2
REGKIND = tagREGKIND

tagTYPEKIND = c_int  # enum
TKIND_ENUM = 0
TKIND_RECORD = 1
TKIND_MODULE = 2
TKIND_INTERFACE = 3
TKIND_DISPATCH = 4
TKIND_COCLASS = 5
TKIND_ALIAS = 6
TKIND_UNION = 7
TKIND_MAX = 8
TYPEKIND = tagTYPEKIND

tagINVOKEKIND = c_int  # enum
INVOKE_FUNC = 1
INVOKE_PROPERTYGET = 2
INVOKE_PROPERTYPUT = 4
INVOKE_PROPERTYPUTREF = 8
INVOKEKIND = tagINVOKEKIND

tagDESCKIND = c_int  # enum
DESCKIND_NONE = 0
DESCKIND_FUNCDESC = 1
DESCKIND_VARDESC = 2
DESCKIND_TYPECOMP = 3
DESCKIND_IMPLICITAPPOBJ = 4
DESCKIND_MAX = 5
DESCKIND = tagDESCKIND

tagVARKIND = c_int  # enum
VAR_PERINSTANCE = 0
VAR_STATIC = 1
VAR_CONST = 2
VAR_DISPATCH = 3
VARKIND = tagVARKIND

tagFUNCKIND = c_int  # enum
FUNC_VIRTUAL = 0
FUNC_PUREVIRTUAL = 1
FUNC_NONVIRTUAL = 2
FUNC_STATIC = 3
FUNC_DISPATCH = 4
FUNCKIND = tagFUNCKIND

tagCALLCONV = c_int  # enum
CC_FASTCALL = 0
CC_CDECL = 1
CC_MSCPASCAL = 2
CC_PASCAL = 2
CC_MACPASCAL = 3
CC_STDCALL = 4
CC_FPFASTCALL = 5
CC_SYSCALL = 6
CC_MPWCDECL = 7
CC_MPWPASCAL = 8
CC_MAX = 9
CALLCONV = tagCALLCONV

IMPLTYPEFLAG_FDEFAULT = 1
IMPLTYPEFLAG_FSOURCE = 2
IMPLTYPEFLAG_FRESTRICTED = 4
IMPLTYPEFLAG_FDEFAULTVTABLE = 8

tagTYPEFLAGS = c_int  # enum
TYPEFLAG_FAPPOBJECT = 1
TYPEFLAG_FCANCREATE = 2
TYPEFLAG_FLICENSED = 4
TYPEFLAG_FPREDECLID = 8
TYPEFLAG_FHIDDEN = 16
TYPEFLAG_FCONTROL = 32
TYPEFLAG_FDUAL = 64
TYPEFLAG_FNONEXTENSIBLE = 128
TYPEFLAG_FOLEAUTOMATION = 256
TYPEFLAG_FRESTRICTED = 512
TYPEFLAG_FAGGREGATABLE = 1024
TYPEFLAG_FREPLACEABLE = 2048
TYPEFLAG_FDISPATCHABLE = 4096
TYPEFLAG_FREVERSEBIND = 8192
TYPEFLAG_FPROXY = 16384
TYPEFLAGS = tagTYPEFLAGS

tagFUNCFLAGS = c_int  # enum
FUNCFLAG_FRESTRICTED = 1
FUNCFLAG_FSOURCE = 2
FUNCFLAG_FBINDABLE = 4
FUNCFLAG_FREQUESTEDIT = 8
FUNCFLAG_FDISPLAYBIND = 16
FUNCFLAG_FDEFAULTBIND = 32
FUNCFLAG_FHIDDEN = 64
FUNCFLAG_FUSESGETLASTERROR = 128
FUNCFLAG_FDEFAULTCOLLELEM = 256
FUNCFLAG_FUIDEFAULT = 512
FUNCFLAG_FNONBROWSABLE = 1024
FUNCFLAG_FREPLACEABLE = 2048
FUNCFLAG_FIMMEDIATEBIND = 4096
FUNCFLAGS = tagFUNCFLAGS

tagVARFLAGS = c_int  # enum
VARFLAG_FREADONLY = 1
VARFLAG_FSOURCE = 2
VARFLAG_FBINDABLE = 4
VARFLAG_FREQUESTEDIT = 8
VARFLAG_FDISPLAYBIND = 16
VARFLAG_FDEFAULTBIND = 32
VARFLAG_FHIDDEN = 64
VARFLAG_FRESTRICTED = 128
VARFLAG_FDEFAULTCOLLELEM = 256
VARFLAG_FUIDEFAULT = 512
VARFLAG_FNONBROWSABLE = 1024
VARFLAG_FREPLACEABLE = 2048
VARFLAG_FIMMEDIATEBIND = 4096
VARFLAGS = tagVARFLAGS

################################################################
# a helper


def _deref_with_release(ptr: "_Pointer[_CT]", release: Callable[..., Any]) -> _CT:
    # Given a POINTER instance, return the pointed to value.
    # Call the 'release' function with 'ptr' to release resources
    # when the value is no longer needed.
    result = ptr[0]
    result.__ref__ = weakref.ref(result, lambda dead: release(ptr))
    return result


# interfaces


class ITypeLib(IUnknown):
    _iid_ = GUID("{00020402-0000-0000-C000-000000000046}")

    # type-checking only methods use the default implementation that comtypes
    # automatically creates for COM methods.
    if TYPE_CHECKING:

        def GetTypeInfoCount(self) -> int:
            """Return the number of type informations"""
            ...

        def GetTypeInfo(self, index: int) -> "ITypeInfo":
            """Load type info by index"""
            ...

        def GetTypeInfoType(self, index: int) -> int:
            """Return the TYPEKIND of type information"""
            ...

        def GetTypeInfoOfGuid(self, guid: GUID) -> "ITypeInfo":
            """Return type information for a guid"""
            ...

        def GetTypeComp(self) -> "ITypeComp":
            """Return an ITypeComp pointer."""
            ...

        def GetDocumentation(
            self, index: int
        ) -> tuple[str, Optional[str], int, Optional[str]]:
            """Return documentation for a type description."""
            ...

        def ReleaseTLibAttr(self, ptla: "_Pointer[TLIBATTR]") -> int:
            """Release TLIBATTR"""
            ...

    def GetLibAttr(self) -> "TLIBATTR":
        """Return type library attributes"""
        return _deref_with_release(
            self._GetLibAttr(),  # type: ignore
            self.ReleaseTLibAttr,
        )

    def IsName(self, name: str, lHashVal: int = 0) -> Optional[str]:
        """Check if there is type information for this name.

        Returns the name with capitalization found in the type
        library, or None.
        """
        namebuf = create_unicode_buffer(name)
        found = BOOL()
        self.__com_IsName(namebuf, lHashVal, byref(found))  # type: ignore
        if found.value:
            return namebuf[:].split("\0", 1)[0]  # type: ignore
        return None

    def FindName(
        self, name: str, lHashVal: int = 0
    ) -> Optional[tuple[int, "ITypeInfo"]]:
        # Hm...
        # Could search for more than one name - should we support this?
        found = ctypes.c_ushort(1)
        tinfo = POINTER(ITypeInfo)()
        memid = MEMBERID()
        self.__com_FindName(  # type: ignore
            name, lHashVal, byref(tinfo), byref(memid), byref(found)
        )
        if found.value:
            return memid.value, tinfo  # type: ignore
        return None


################


@overload
def fix_name(name: None) -> None: ...
@overload
def fix_name(name: str) -> str: ...
def fix_name(name):
    # Some typelibs contain BSTR with embedded NUL characters,
    # probably the len of the BSTR is wrong.
    if name is None:
        return name
    return name.split("\0")[0]


class ITypeInfo(IUnknown):
    _iid_ = GUID("{00020401-0000-0000-C000-000000000046}")

    if TYPE_CHECKING:

        def GetTypeComp(self) -> "ITypeComp":
            """Return ITypeComp pointer for this type"""
            ...

        def GetRefTypeOfImplType(self, index: int) -> int:
            """Get the reftype of an implemented type"""
            ...

        def GetImplTypeFlags(self, index: int) -> int:
            """Get IMPLTYPEFLAGS"""
            ...

        # not yet wrapped
        # STDMETHOD(
        #     HRESULT, 'Invoke', [
        #         PVOID, MEMBERID, WORD, POINTER(DISPPARAMS),
        #         POINTER(VARIANT), POINTER(EXCEPINFO), POINTER(UINT)
        #     ]
        # ),
        def GetDllEntry(
            self, memid: int, invkind: int
        ) -> tuple[Optional[str], Optional[str], int]:
            """Return the dll name, function name, and ordinal for a function
            and invkind.
            """
            ...

        def GetRefTypeInfo(self, href: int) -> "ITypeInfo":
            """Get type info for reftype"""
            ...

        def GetMops(self, index: int) -> Optional[str]:
            """Get marshalling opcodes (whatever that is...)"""
            ...

        def GetContainingTypeLib(self) -> tuple[ITypeLib, int]:
            """Return index into and the containing type lib itself"""
            ...

        def ReleaseTypeAttr(self, pTypeAttr: "_Pointer[TYPEATTR]") -> int:
            """Releases a TYPEATTR previously returned by GetTypeAttr"""
            ...

        def ReleaseFuncDesc(self, pFuncDesc: "_Pointer[FUNCDESC]") -> int:
            """Releases a FUNCDESC previously returned by GetFuncDesc"""
            ...

        def ReleaseVarDesc(self, pVarDesc: "_Pointer[VARDESC]") -> int:
            """Releases a VARDESC previously returned by VarDesc"""
            ...

    def GetTypeAttr(self) -> "TYPEATTR":
        """Return the TYPEATTR for this type"""
        return _deref_with_release(
            self._GetTypeAttr(),  # type: ignore
            self.ReleaseTypeAttr,
        )

    def GetDocumentation(
        self, memid: int
    ) -> tuple[str, Optional[str], int, Optional[str]]:
        """Return name, docstring, helpcontext, and helpfile for 'memid'."""
        name, doc, helpctx, helpfile = self._GetDocumentation(memid)  # type: ignore
        return fix_name(name), fix_name(doc), helpctx, fix_name(helpfile)

    def GetFuncDesc(self, index: int) -> "FUNCDESC":
        """Return FUNCDESC for index"""
        return _deref_with_release(
            self._GetFuncDesc(index),  # type: ignore
            self.ReleaseFuncDesc,
        )

    def GetVarDesc(self, index: int) -> "VARDESC":
        """Return VARDESC for index"""
        return _deref_with_release(
            self._GetVarDesc(index),  # type: ignore
            self.ReleaseVarDesc,
        )

    def GetNames(self, memid: int, count: int = 1) -> list[str]:
        """Return names for memid"""
        names = (BSTR * count)()
        cnames = ctypes.c_uint()
        self.__com_GetNames(memid, names, count, byref(cnames))  # type: ignore
        return names[: cnames.value]

    def GetIDsOfNames(self, *names: str) -> list[int]:
        """Maps function and argument names to identifiers"""
        rgsznames = (c_wchar_p * len(names))(*names)
        ids = (MEMBERID * len(names))()
        self.__com_GetIDsOfNames(rgsznames, len(names), ids)  # type: ignore
        return ids[:]

    def AddressOfMember(self, memid: int, invkind: int) -> int:
        """Get the address of a function in a dll"""
        p = c_void_p()
        self.__com_AddressOfMember(memid, invkind, byref(p))  # type: ignore
        return p.value  # type: ignore

    def CreateInstance(
        self,
        punkouter: Optional[type["_Pointer[IUnknown]"]] = None,
        interface: type[_T_IUnknown] = IUnknown,
        iid: Optional[GUID] = None,
    ) -> _T_IUnknown:
        if iid is None:
            iid = interface._iid_
        return self._CreateInstance(punkouter, byref(interface._iid_))  # type: ignore


################


class ITypeComp(IUnknown):
    _iid_ = GUID("{00020403-0000-0000-C000-000000000046}")

    def Bind(
        self, name: str, flags: int = 0, lHashVal: int = 0
    ) -> _UnionT[
        tuple[Literal["function"], "FUNCDESC"],
        tuple[Literal["variable"], "VARDESC"],
        tuple[Literal["type"], "ITypeComp"],
        None,
    ]:
        """Bind to a name"""
        bindptr = BINDPTR()
        desckind = DESCKIND()
        ti: ITypeInfo = POINTER(ITypeInfo)()  # type: ignore
        self.__com_Bind(  # type: ignore
            name, lHashVal, flags, byref(ti), byref(desckind), byref(bindptr)
        )
        kind = desckind.value
        if kind == DESCKIND_FUNCDESC:
            fd = _deref_with_release(bindptr.lpfuncdesc, ti.ReleaseFuncDesc)
            return "function", fd
        elif kind == DESCKIND_VARDESC:
            vd = _deref_with_release(bindptr.lpvardesc, ti.ReleaseVarDesc)
            return "variable", vd
        elif kind == DESCKIND_TYPECOMP:
            return "type", bindptr.lptcomp
        elif kind == DESCKIND_IMPLICITAPPOBJ:
            # `DESCKIND_IMPLICITAPPOBJ` is rare; mainly for Office Application.
            # It indicates a global application object (`TYPEFLAG_FAPPOBJECT`).
            # Few other COM components use this highly specialized flag.
            # Thus, this path is unlikely to be hit in common scenarios.
            raise NotImplementedError
        elif kind == DESCKIND_NONE:
            raise NameError("Name %s not found" % name)
        # `DESCKIND_MAX` is an end-of-enumeration marker, not a valid return
        # from `ITypeComp::Bind` in COM. If returned, it implies a malformed
        # type library. The current implementation implicitly returns `None`.

    def BindType(self, name: str, lHashVal: int = 0) -> tuple[ITypeInfo, "ITypeComp"]:
        """Bind a type, and return both the typeinfo and typecomp for it."""
        ti = POINTER(ITypeInfo)()
        tc = POINTER(ITypeComp)()
        self.__com_BindType(name, lHashVal, byref(ti), byref(tc))  # type: ignore
        return ti, tc  # type: ignore


################


class ICreateTypeLib(IUnknown):
    _iid_ = GUID("{00020406-0000-0000-C000-000000000046}")
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 2149


class ICreateTypeLib2(ICreateTypeLib):
    _iid_ = GUID("{0002040F-0000-0000-C000-000000000046}")


class ICreateTypeInfo(IUnknown):
    _iid_ = GUID("{00020405-0000-0000-C000-000000000046}")
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 915

    def SetFuncAndParamNames(self, index: int, *names: str) -> int:
        rgszNames = (c_wchar_p * len(names))()
        for i, n in enumerate(names):
            rgszNames[i] = n
        return self._SetFuncAndParamNames(index, rgszNames, len(names))  # type: ignore


class IRecordInfo(IUnknown):
    # C:/vc98/include/OAIDL.H 5974
    _iid_ = GUID("{0000002F-0000-0000-C000-000000000046}")

    def GetFieldNames(self, *args: Any) -> list[Optional[str]]:
        count = ctypes.c_ulong()
        self.__com_GetFieldNames(count, None)  # type: ignore
        array = (BSTR * count.value)()
        self.__com_GetFieldNames(count, array)  # type: ignore
        result = array[:]
        # XXX Should SysFreeString the array contents. How to?
        return result

    if TYPE_CHECKING:
        # def RecordInit
        # def RecordClear
        def RecordCopy(
            self, pvExisting: hints.Incomplete, pvNew: hints.Incomplete
        ) -> hints.Hresult: ...
        def GetGuid(self) -> GUID: ...
        def GetName(self) -> str: ...
        def GetSize(self) -> int: ...
        def GetTypeInfo(self) -> ITypeInfo: ...
        # def GetField
        # def GetFieldNoCopy
        # def PutField
        # def PutFieldNoCopy
        def IsMatchingType(self, value: "IRecordInfo") -> bool: ...
        # def RecordCreate
        def RecordCreateCopy(self, pvSource: hints.Incomplete) -> int: ...
        def RecordDestroy(self, pvRecord: hints.Incomplete) -> hints.Hresult: ...


IRecordInfo._methods_ = [
    COMMETHOD([], HRESULT, "RecordInit", (["in"], c_void_p, "pvNew")),
    COMMETHOD([], HRESULT, "RecordClear", (["in"], c_void_p, "pvExisting")),
    COMMETHOD(
        [],
        HRESULT,
        "RecordCopy",
        (["in"], c_void_p, "pvExisting"),
        (["in"], c_void_p, "pvNew"),
    ),
    COMMETHOD([], HRESULT, "GetGuid", (["out"], POINTER(GUID), "pguid")),
    COMMETHOD([], HRESULT, "GetName", (["out"], POINTER(BSTR), "pbstrName")),
    COMMETHOD([], HRESULT, "GetSize", (["out"], POINTER(ctypes.c_ulong), "pcbSize")),
    COMMETHOD(
        [], HRESULT, "GetTypeInfo", (["out"], POINTER(POINTER(ITypeInfo)), "ppTypeInfo")
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetField",
        (["in"], c_void_p, "pvData"),
        (["in"], c_wchar_p, "szFieldName"),
        (["out"], POINTER(VARIANT), "pvarField"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetFieldNoCopy",
        (["in"], c_void_p, "pvData"),
        (["in"], c_wchar_p, "szFieldName"),
        (["out"], POINTER(VARIANT), "pvarField"),
        (["out"], POINTER(c_void_p), "ppvDataCArray"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "PutField",
        (["in"], ctypes.c_ulong, "wFlags"),
        (["in"], c_void_p, "pvData"),
        (["in"], c_wchar_p, "szFieldName"),
        (["in"], POINTER(VARIANT), "pvarField"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "PutFieldNoCopy",
        (["in"], ctypes.c_ulong, "wFlags"),
        (["in"], c_void_p, "pvData"),
        (["in"], c_wchar_p, "szFieldName"),
        (["in"], POINTER(VARIANT), "pvarField"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetFieldNames",
        (["in", "out"], POINTER(ctypes.c_ulong), "pcNames"),
        (["in"], POINTER(BSTR), "rgBstrNames"),
    ),
    COMMETHOD([], BOOL, "IsMatchingType", (["in"], POINTER(IRecordInfo))),
    COMMETHOD([], HRESULT, "RecordCreate"),
    COMMETHOD(
        [],
        HRESULT,
        "RecordCreateCopy",
        (["in"], c_void_p, "pvSource"),
        (["out"], POINTER(c_void_p), "ppvDest"),
    ),
    COMMETHOD([], HRESULT, "RecordDestroy", (["in"], c_void_p, "pvRecord")),
]


################################################################
# functions
_oleaut32 = OleDLL("oleaut32")

_GetRecordInfoFromTypeInfo = _oleaut32.GetRecordInfoFromTypeInfo
_GetRecordInfoFromTypeInfo.argtypes = [
    POINTER(ITypeInfo),
    POINTER(POINTER(IRecordInfo)),
]
_GetRecordInfoFromTypeInfo.restype = HRESULT

_GetRecordInfoFromGuids = _oleaut32.GetRecordInfoFromGuids
_GetRecordInfoFromGuids.argtypes = [
    POINTER(GUID),
    ULONG,
    ULONG,
    LCID,
    POINTER(GUID),
    POINTER(POINTER(IRecordInfo)),
]
_GetRecordInfoFromGuids.restype = HRESULT

_LoadRegTypeLib = _oleaut32.LoadRegTypeLib
_LoadRegTypeLib.argtypes = [POINTER(GUID), WORD, WORD, LCID, POINTER(POINTER(ITypeLib))]
_LoadRegTypeLib.restype = HRESULT

_LoadTypeLibEx = _oleaut32.LoadTypeLibEx
_LoadTypeLibEx.argtypes = [LPCOLESTR, REGKIND, POINTER(POINTER(ITypeLib))]
_LoadTypeLibEx.restype = HRESULT

_LoadTypeLib = _oleaut32.LoadTypeLib
_LoadTypeLib.argtypes = [LPCOLESTR, POINTER(POINTER(ITypeLib))]
_LoadTypeLib.restype = HRESULT

_UnRegisterTypeLib = _oleaut32.UnRegisterTypeLib
_UnRegisterTypeLib.argtypes = [POINTER(GUID), WORD, WORD, LCID, SYSKIND]
_UnRegisterTypeLib.restype = HRESULT

_RegisterTypeLib = _oleaut32.RegisterTypeLib
_RegisterTypeLib.argtypes = [POINTER(ITypeLib), LPCOLESTR, LPCOLESTR]
_RegisterTypeLib.restype = HRESULT

_CreateTypeLib2 = _oleaut32.CreateTypeLib2
_CreateTypeLib2.argtypes = [SYSKIND, LPCOLESTR, POINTER(POINTER(ICreateTypeLib2))]
_CreateTypeLib2.restype = HRESULT

_QueryPathOfRegTypeLib = _oleaut32.QueryPathOfRegTypeLib
_QueryPathOfRegTypeLib.argtypes = [POINTER(GUID), USHORT, USHORT, LCID, POINTER(BSTR)]
_QueryPathOfRegTypeLib.restype = HRESULT

_kernel32 = WinDLL("kernel32")

_GetModuleFileNameW = _kernel32.GetModuleFileNameW
_GetModuleFileNameW.argtypes = [HMODULE, LPWSTR, DWORD]
_GetModuleFileNameW.restype = DWORD


def GetRecordInfoFromTypeInfo(tinfo: ITypeInfo) -> IRecordInfo:
    """Return an IRecordInfo pointer to the UDT described in tinfo"""
    ri = POINTER(IRecordInfo)()
    _GetRecordInfoFromTypeInfo(tinfo, byref(ri))
    return ri  # type: ignore


def GetRecordInfoFromGuids(
    rGuidTypeLib: str, verMajor: int, verMinor: int, lcid: int, rGuidTypeInfo: str
) -> IRecordInfo:
    ri = POINTER(IRecordInfo)()
    _GetRecordInfoFromGuids(
        byref(GUID(rGuidTypeLib)),
        verMajor,
        verMinor,
        lcid,
        byref(GUID(rGuidTypeInfo)),
        byref(ri),
    )
    return ri  # type: ignore


def LoadRegTypeLib(
    guid: _UnionT[str, GUID], wMajorVerNum: int, wMinorVerNum: int, lcid: int = 0
) -> ITypeLib:
    """Load a registered type library"""
    tlib = POINTER(ITypeLib)()
    _LoadRegTypeLib(byref(GUID(guid)), wMajorVerNum, wMinorVerNum, lcid, byref(tlib))
    return tlib  # type: ignore


def LoadTypeLibEx(szFile: str, regkind: int = REGKIND_NONE) -> ITypeLib:
    """Load, and optionally register a type library file"""
    ptl = POINTER(ITypeLib)()
    _LoadTypeLibEx(c_wchar_p(szFile), regkind, byref(ptl))
    return ptl  # type: ignore


def LoadTypeLib(szFile: str) -> ITypeLib:
    """Load and register a type library file"""
    tlib = POINTER(ITypeLib)()
    _LoadTypeLib(c_wchar_p(szFile), byref(tlib))
    return tlib  # type: ignore


def UnRegisterTypeLib(
    libID: str,
    wVerMajor: int,
    wVerMinor: int,
    lcid: int = 0,
    syskind: int = (SYS_WIN64 if is_64_bit else SYS_WIN32),
) -> int:
    """Unregister a registered type library"""
    return _UnRegisterTypeLib(byref(GUID(libID)), wVerMajor, wVerMinor, lcid, syskind)


def RegisterTypeLib(
    tlib: ITypeLib, fullpath: str, helpdir: Optional[str] = None
) -> int:
    """Register a type library in the registry"""
    return _RegisterTypeLib(tlib, c_wchar_p(fullpath), c_wchar_p(helpdir))


def CreateTypeLib(filename: str, syskind: int = SYS_WIN32) -> ICreateTypeLib2:
    """Return a ICreateTypeLib2 pointer"""
    ctlib = POINTER(ICreateTypeLib2)()
    _CreateTypeLib2(syskind, c_wchar_p(filename), byref(ctlib))
    return ctlib  # type: ignore


def QueryPathOfRegTypeLib(
    libid: str, wVerMajor: int, wVerMinor: int, lcid: int = 0
) -> str:
    """
    Retrieve the path of a registered type library.

    This function interacts with the Windows registry to locate the path of a
    registered type library given its GUID, version, and locale.

    Args:
        libid (str): The GUID of the type library as a string.
        wVerMajor (int): The major version of the type library.
        wVerMinor (int): The minor version of the type library.
        lcid (int, optional): The locale ID of the type library.

    Returns:
        str: The path of the registered type library.

    Raises:
        OSError: If QueryPathOfRegTypeLib fails.
    """

    pathname = BSTR()
    _QueryPathOfRegTypeLib(
        byref(GUID(libid)), wVerMajor, wVerMinor, lcid, byref(pathname)
    )
    return pathname.value.split("\0")[0]


def GetModuleFileName(handle: Optional[int], maxsize: int) -> str:
    """Returns the fullpath of the loaded module specified by the handle.
    If the handle is NULL, returns the executable file path of the current process.

    https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew
    """
    buf = create_unicode_buffer(maxsize)
    # In a Python virtual environment on Windows, the Windows API
    # `GetModuleFileNameW(NULL, ..., ...)` returns the path to the base
    # `python.exe` (located within `sys.base_prefix`, not same as
    # `sys.executable`).
    length = _GetModuleFileNameW(handle, buf, maxsize)
    if not length:
        raise ctypes.WinError()
    return buf.value[:length]


################################################################
# Structures


class tagTLIBATTR(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 4437
    if TYPE_CHECKING:
        guid: GUID
        lcid: int
        syskind: int
        wMajorVerNum: int
        wMinorVerNum: int
        wLibFlags: int

    def __repr__(self):
        return f"TLIBATTR(GUID={self.guid}, Version={self.wMajorVerNum}.{self.wMinorVerNum}, LCID={self.lcid}, FLags=0x{self.wLibFlags:x})"


TLIBATTR = tagTLIBATTR


class tagTYPEATTR(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 672
    if TYPE_CHECKING:
        guid: GUID
        lcid: int
        dwReserved: int
        memidConstructor: int
        memidDestructor: int
        lpstrSchema: str
        cbSizeInstance: int
        typekind: int
        cFuncs: int
        cVars: int
        cImplTypes: int
        cbSizeVft: int
        cbAlignment: int
        wTypeFlags: int
        wMajorVerNum: int
        wMinorVerNum: int
        tdescAlias: "TYPEDESC"
        idldescType: "IDLDESC"

    def __repr__(self):
        return f"TYPEATTR(GUID={self.guid}, typekind={self.typekind}, funcs={self.cFuncs}, vars={self.cVars}, impltypes={self.cImplTypes})"


TYPEATTR = tagTYPEATTR


class tagFUNCDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 769
    if TYPE_CHECKING:
        memid: int
        lprgscode: int
        lprgelemdescParam: Sequence["ELEMDESC"]
        funckind: int
        invkind: int
        callconv: int
        cParams: int
        cParamsOpt: int
        oVft: int
        cScodes: int
        elemdescFunc: "ELEMDESC"
        wFuncFlags: int

    def __repr__(self):
        return (
            f"FUNCDESC("
            f"memid={self.memid}, "
            f"cParams={self.cParams}, "
            f"cParamsOpt={self.cParamsOpt}, "
            f"callconv={self.callconv}, "
            f"invkind={self.invkind}, "
            f"funckind={self.funckind}"
            f")"
        )


FUNCDESC = tagFUNCDESC


class tagVARDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 803
    if TYPE_CHECKING:
        memid: int
        lpstrSchema: str
        _: "N10tagVARDESC5DOLLAR_205E"
        elemdescVar: "ELEMDESC"
        wVarFlags: int
        varkind: int


VARDESC = tagVARDESC


class tagBINDPTR(ctypes.Union):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 3075
    if TYPE_CHECKING:
        lpfuncdesc: _Pointer["FUNCDESC"]
        lpvardesc: _Pointer["VARDESC"]
        lptcomp: ITypeComp


BINDPTR = tagBINDPTR


class tagTYPEDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 582
    if TYPE_CHECKING:
        _: "N11tagTYPEDESC5DOLLAR_203E"
        vt: int


TYPEDESC = tagTYPEDESC


class tagIDLDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 633
    if TYPE_CHECKING:
        dwReserved: int
        wIDLFlags: int


IDLDESC = tagIDLDESC


class tagARRAYDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 594
    if TYPE_CHECKING:
        tdescElem: TYPEDESC
        cDims: int
        rgbounds: Sequence["SAFEARRAYBOUND"]


################################################################
# interface vtbl definitions

ICreateTypeLib._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 2149
    COMMETHOD(
        [],
        HRESULT,
        "CreateTypeInfo",
        (["in"], LPOLESTR, "szName"),
        (["in"], TYPEKIND, "tkind"),
        (["out"], POINTER(POINTER(ICreateTypeInfo)), "ppCTInfo"),
    ),
    STDMETHOD(HRESULT, "SetName", [LPOLESTR]),
    STDMETHOD(HRESULT, "SetVersion", [WORD, WORD]),
    STDMETHOD(HRESULT, "SetGuid", [POINTER(GUID)]),
    STDMETHOD(HRESULT, "SetDocString", [LPOLESTR]),
    STDMETHOD(HRESULT, "SetHelpFileName", [LPOLESTR]),
    STDMETHOD(HRESULT, "SetHelpContext", [DWORD]),
    STDMETHOD(HRESULT, "SetLcid", [LCID]),
    STDMETHOD(HRESULT, "SetLibFlags", [UINT]),
    STDMETHOD(HRESULT, "SaveAllChanges", []),
]

ICreateTypeLib2._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 2444
    STDMETHOD(HRESULT, "DeleteTypeInfo", [POINTER(ITypeInfo)]),
    STDMETHOD(HRESULT, "SetCustData", [POINTER(GUID), POINTER(VARIANT)]),
    STDMETHOD(HRESULT, "SetHelpStringContext", [ULONG]),
    STDMETHOD(HRESULT, "SetHelpStringDll", [LPOLESTR]),
]

ITypeLib._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 4455
    COMMETHOD([], UINT, "GetTypeInfoCount"),
    COMMETHOD(
        [],
        HRESULT,
        "GetTypeInfo",
        (["in"], UINT, "index"),
        (["out"], POINTER(POINTER(ITypeInfo))),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetTypeInfoType",
        (["in"], UINT, "index"),
        (["out"], POINTER(TYPEKIND)),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetTypeInfoOfGuid",
        (["in"], POINTER(GUID)),
        (["out"], POINTER(POINTER(ITypeInfo))),
    ),
    COMMETHOD([], HRESULT, "GetLibAttr", (["out"], POINTER(POINTER(TLIBATTR)))),
    COMMETHOD([], HRESULT, "GetTypeComp", (["out"], POINTER(POINTER(ITypeComp)))),
    COMMETHOD(
        [],
        HRESULT,
        "GetDocumentation",
        (["in"], INT, "index"),
        (["out"], POINTER(BSTR)),
        (["out"], POINTER(BSTR)),
        (["out"], POINTER(DWORD)),
        (["out"], POINTER(BSTR)),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "IsName",
        # IsName changes the casing of the passed in name to
        # match that in the type library.  In the automatically
        # wrapped version of this method, ctypes would pass a
        # Python unicode string which would then be changed -
        # very bad.  So we have (see above) to implement the
        # IsName method manually.
        (["in", "out"], LPOLESTR, "name"),
        (["in", "optional"], DWORD, "lHashVal", 0),
        (["out"], POINTER(BOOL)),
    ),
    STDMETHOD(
        HRESULT,
        "FindName",
        [
            LPOLESTR,
            DWORD,
            POINTER(POINTER(ITypeInfo)),
            POINTER(MEMBERID),
            POINTER(USHORT),
        ],
    ),
    COMMETHOD([], None, "ReleaseTLibAttr", (["in"], POINTER(TLIBATTR))),
]

ITypeInfo._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 3230
    COMMETHOD(
        [], HRESULT, "GetTypeAttr", (["out"], POINTER(POINTER(TYPEATTR)), "ppTypeAttr")
    ),
    COMMETHOD([], HRESULT, "GetTypeComp", (["out"], POINTER(POINTER(ITypeComp)))),
    COMMETHOD(
        [],
        HRESULT,
        "GetFuncDesc",
        (["in"], UINT, "index"),
        (["out"], POINTER(POINTER(FUNCDESC))),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetVarDesc",
        (["in"], UINT, "index"),
        (["out"], POINTER(POINTER(VARDESC))),
    ),
    STDMETHOD(HRESULT, "GetNames", [MEMBERID, POINTER(BSTR), UINT, POINTER(UINT)]),
    COMMETHOD(
        [],
        HRESULT,
        "GetRefTypeOfImplType",
        (["in"], UINT, "index"),
        (["out"], POINTER(HREFTYPE)),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetImplTypeFlags",
        (["in"], UINT, "index"),
        (["out"], POINTER(INT)),
    ),
    # STDMETHOD(HRESULT, 'GetIDsOfNames', [POINTER(LPOLESTR), UINT, POINTER(MEMBERID)]),
    # this one changed, to accept c_wchar_p array
    STDMETHOD(HRESULT, "GetIDsOfNames", [POINTER(c_wchar_p), UINT, POINTER(MEMBERID)]),
    STDMETHOD(
        HRESULT,
        "Invoke",
        [
            PVOID,
            MEMBERID,
            WORD,
            POINTER(DISPPARAMS),
            POINTER(VARIANT),
            POINTER(EXCEPINFO),
            POINTER(UINT),
        ],
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetDocumentation",
        (["in"], MEMBERID, "memid"),
        (["out"], POINTER(BSTR), "pBstrName"),
        (["out"], POINTER(BSTR), "pBstrDocString"),
        (["out"], POINTER(DWORD), "pdwHelpContext"),
        (["out"], POINTER(BSTR), "pBstrHelpFile"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetDllEntry",
        (["in"], MEMBERID, "index"),
        (["in"], INVOKEKIND, "invkind"),
        (["out"], POINTER(BSTR), "pBstrDllName"),
        (["out"], POINTER(BSTR), "pBstrName"),
        (["out"], POINTER(WORD), "pwOrdinal"),
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetRefTypeInfo",
        (["in"], HREFTYPE, "hRefType"),
        (["out"], POINTER(POINTER(ITypeInfo))),
    ),
    STDMETHOD(HRESULT, "AddressOfMember", [MEMBERID, INVOKEKIND, POINTER(PVOID)]),
    COMMETHOD(
        [],
        HRESULT,
        "CreateInstance",
        (["in"], POINTER(IUnknown), "pUnkOuter"),
        (["in"], POINTER(IID), "refiid"),
        (["out"], POINTER(POINTER(IUnknown))),
    ),
    COMMETHOD(
        [], HRESULT, "GetMops", (["in"], MEMBERID, "memid"), (["out"], POINTER(BSTR))
    ),
    COMMETHOD(
        [],
        HRESULT,
        "GetContainingTypeLib",
        (["out"], POINTER(POINTER(ITypeLib))),
        (["out"], POINTER(UINT)),
    ),
    COMMETHOD([], None, "ReleaseTypeAttr", (["in"], POINTER(TYPEATTR))),
    COMMETHOD([], None, "ReleaseFuncDesc", (["in"], POINTER(FUNCDESC))),
    COMMETHOD([], None, "ReleaseVarDesc", (["in"], POINTER(VARDESC))),
]

ITypeComp._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 3090
    STDMETHOD(
        HRESULT,
        "Bind",
        [
            LPOLESTR,
            DWORD,
            WORD,
            POINTER(POINTER(ITypeInfo)),
            POINTER(DESCKIND),
            POINTER(BINDPTR),
        ],
    ),
    STDMETHOD(
        HRESULT,
        "BindType",
        [LPOLESTR, DWORD, POINTER(POINTER(ITypeInfo)), POINTER(POINTER(ITypeComp))],
    ),
]

ICreateTypeInfo._methods_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 915
    STDMETHOD(HRESULT, "SetGuid", [POINTER(GUID)]),
    STDMETHOD(HRESULT, "SetTypeFlags", [UINT]),
    STDMETHOD(HRESULT, "SetDocString", [LPOLESTR]),
    STDMETHOD(HRESULT, "SetHelpContext", [DWORD]),
    STDMETHOD(HRESULT, "SetVersion", [WORD, WORD]),
    #    STDMETHOD(HRESULT, 'AddRefTypeInfo', [POINTER(ITypeInfo), POINTER(HREFTYPE)]),
    COMMETHOD(
        [],
        HRESULT,
        "AddRefTypeInfo",
        (["in"], POINTER(ITypeInfo)),
        (["out"], POINTER(HREFTYPE)),
    ),
    STDMETHOD(HRESULT, "AddFuncDesc", [UINT, POINTER(FUNCDESC)]),
    STDMETHOD(HRESULT, "AddImplType", [UINT, HREFTYPE]),
    STDMETHOD(HRESULT, "SetImplTypeFlags", [UINT, INT]),
    STDMETHOD(HRESULT, "SetAlignment", [WORD]),
    STDMETHOD(HRESULT, "SetSchema", [LPOLESTR]),
    STDMETHOD(HRESULT, "AddVarDesc", [UINT, POINTER(VARDESC)]),
    STDMETHOD(HRESULT, "SetFuncAndParamNames", [UINT, POINTER(c_wchar_p), UINT]),
    STDMETHOD(HRESULT, "SetVarName", [UINT, LPOLESTR]),
    STDMETHOD(HRESULT, "SetTypeDescAlias", [POINTER(TYPEDESC)]),
    STDMETHOD(HRESULT, "DefineFuncAsDllEntry", [UINT, LPOLESTR, LPOLESTR]),
    STDMETHOD(HRESULT, "SetFuncDocString", [UINT, LPOLESTR]),
    STDMETHOD(HRESULT, "SetVarDocString", [UINT, LPOLESTR]),
    STDMETHOD(HRESULT, "SetFuncHelpContext", [UINT, DWORD]),
    STDMETHOD(HRESULT, "SetVarHelpContext", [UINT, DWORD]),
    STDMETHOD(HRESULT, "SetMops", [UINT, BSTR]),
    STDMETHOD(HRESULT, "SetTypeIdldesc", [POINTER(IDLDESC)]),
    STDMETHOD(HRESULT, "LayOut", []),
]


class IProvideClassInfo(IUnknown):
    _iid_ = GUID("{B196B283-BAB4-101A-B69C-00AA00341D07}")
    if TYPE_CHECKING:

        def GetClassInfo(self) -> ITypeInfo:
            """Returns the ITypeInfo interface for the object's coclass type
            information.
            """
            ...

    _methods_ = [
        COMMETHOD(
            [], HRESULT, "GetClassInfo", (["out"], POINTER(POINTER(ITypeInfo)), "ppTI")
        )
    ]


# Flags used to specify the kind of information requested from an object.
GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1


class IProvideClassInfo2(IProvideClassInfo):
    _iid_ = GUID("{A6BC3AC0-DBAA-11CE-9DE3-00AA004BB851}")
    if TYPE_CHECKING:

        def GetGUID(self, dwGuidKind: int) -> GUID:
            """Returns the GUID for the object's outgoing IID for its default
            event set
            """
            ...

    _methods_ = [
        COMMETHOD(
            [],
            HRESULT,
            "GetGUID",
            (["in"], DWORD, "dwGuidKind"),
            (["out", "retval"], POINTER(GUID), "pGUID"),
        )
    ]


################################################################
# Structure fields

tagTLIBATTR._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 4437
    ("guid", GUID),
    ("lcid", LCID),
    ("syskind", SYSKIND),
    ("wMajorVerNum", WORD),
    ("wMinorVerNum", WORD),
    ("wLibFlags", WORD),
]


class N11tagTYPEDESC5DOLLAR_203E(ctypes.Union):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 584
    if TYPE_CHECKING:
        lptdesc: _Pointer[tagTYPEDESC]
        lpadesc: _Pointer[tagARRAYDESC]
        hreftype: int


N11tagTYPEDESC5DOLLAR_203E._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 584
    ("lptdesc", POINTER(tagTYPEDESC)),
    ("lpadesc", POINTER(tagARRAYDESC)),
    ("hreftype", HREFTYPE),
]
tagTYPEDESC._anonymous_ = ("_",)
tagTYPEDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 582
    # Unnamed field renamed to '_'
    ("_", N11tagTYPEDESC5DOLLAR_203E),
    ("vt", VARTYPE),
]
tagIDLDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 633
    ("dwReserved", ULONG_PTR),
    ("wIDLFlags", USHORT),
]
tagTYPEATTR._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 672
    ("guid", GUID),
    ("lcid", LCID),
    ("dwReserved", DWORD),
    ("memidConstructor", MEMBERID),
    ("memidDestructor", MEMBERID),
    ("lpstrSchema", LPOLESTR),
    ("cbSizeInstance", DWORD),
    ("typekind", TYPEKIND),
    ("cFuncs", WORD),
    ("cVars", WORD),
    ("cImplTypes", WORD),
    ("cbSizeVft", WORD),
    ("cbAlignment", WORD),
    ("wTypeFlags", WORD),
    ("wMajorVerNum", WORD),
    ("wMinorVerNum", WORD),
    ("tdescAlias", TYPEDESC),
    ("idldescType", IDLDESC),
]


class N10tagVARDESC5DOLLAR_205E(ctypes.Union):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 807
    if TYPE_CHECKING:
        oInst: int
        lpvarValue: _Pointer[VARIANT]


N10tagVARDESC5DOLLAR_205E._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 807
    ("oInst", DWORD),
    ("lpvarValue", POINTER(VARIANT)),
]


class tagELEMDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 661
    if TYPE_CHECKING:
        tdesc: TYPEDESC
        _: "N11tagELEMDESC5DOLLAR_204E"


class N11tagELEMDESC5DOLLAR_204E(ctypes.Union):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 663
    if TYPE_CHECKING:
        idldesc: IDLDESC
        paramdesc: "PARAMDESC"


class tagPARAMDESC(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 609
    if TYPE_CHECKING:
        pparamdescex: "_Pointer[tagPARAMDESCEX]"
        wParamFlags: int


class tagPARAMDESCEX(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 601
    if TYPE_CHECKING:
        cBytes: int
        varDefaultValue: VARIANTARG


LPPARAMDESCEX = POINTER(tagPARAMDESCEX)

tagPARAMDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 609
    ("pparamdescex", LPPARAMDESCEX),
    ("wParamFlags", USHORT),
]
PARAMDESC = tagPARAMDESC

N11tagELEMDESC5DOLLAR_204E._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 663
    ("idldesc", IDLDESC),
    ("paramdesc", PARAMDESC),
]
tagELEMDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 661
    ("tdesc", TYPEDESC),
    # Unnamed field renamed to '_'
    ("_", N11tagELEMDESC5DOLLAR_204E),
]
ELEMDESC = tagELEMDESC

tagVARDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 803
    ("memid", MEMBERID),
    ("lpstrSchema", LPOLESTR),
    # Unnamed field renamed to '_'
    ("_", N10tagVARDESC5DOLLAR_205E),
    ("elemdescVar", ELEMDESC),
    ("wVarFlags", WORD),
    ("varkind", VARKIND),
]
tagBINDPTR._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 3075
    ("lpfuncdesc", POINTER(FUNCDESC)),
    ("lpvardesc", POINTER(VARDESC)),
    ("lptcomp", POINTER(ITypeComp)),
]

tagFUNCDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 769
    ("memid", MEMBERID),
    ("lprgscode", POINTER(SCODE)),
    ("lprgelemdescParam", POINTER(ELEMDESC)),
    ("funckind", FUNCKIND),
    ("invkind", INVOKEKIND),
    ("callconv", CALLCONV),
    ("cParams", SHORT),
    ("cParamsOpt", SHORT),
    ("oVft", SHORT),
    ("cScodes", SHORT),
    ("elemdescFunc", ELEMDESC),
    ("wFuncFlags", WORD),
]

tagPARAMDESCEX._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 601
    ("cBytes", DWORD),
    ("varDefaultValue", VARIANTARG),
]


class tagSAFEARRAYBOUND(ctypes.Structure):
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 226
    if TYPE_CHECKING:
        cElements: int
        lLbound: int
    _fields_ = [
        ("cElements", DWORD),
        ("lLbound", LONG),
    ]


SAFEARRAYBOUND = tagSAFEARRAYBOUND

tagARRAYDESC._fields_ = [
    # C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 594
    ("tdescElem", TYPEDESC),
    ("cDims", USHORT),
    ("rgbounds", SAFEARRAYBOUND * 1),
]


# fmt: off
__known_symbols__ = [
    "tagARRAYDESC", "BINDPTR", "tagBINDPTR", "CALLCONV", "tagCALLCONV",
    "CC_CDECL", "CC_FASTCALL", "CC_FPFASTCALL", "CC_MACPASCAL", "CC_MAX",
    "CC_MPWCDECL", "CC_MPWPASCAL", "CC_MSCPASCAL", "CC_PASCAL", "CC_STDCALL",
    "CC_SYSCALL", "CreateTypeLib", "DESCKIND", "tagDESCKIND",
    "DESCKIND_FUNCDESC", "DESCKIND_IMPLICITAPPOBJ", "DESCKIND_MAX",
    "DESCKIND_NONE", "DESCKIND_TYPECOMP", "DESCKIND_VARDESC", "ELEMDESC",
    "tagELEMDESC", "FUNC_DISPATCH", "FUNC_NONVIRTUAL", "FUNC_PUREVIRTUAL",
    "FUNC_STATIC", "FUNC_VIRTUAL", "FUNCDESC", "tagFUNCDESC",
    "FUNCFLAG_FBINDABLE", "FUNCFLAG_FDEFAULTBIND", "FUNCFLAG_FDEFAULTCOLLELEM",
    "FUNCFLAG_FDISPLAYBIND", "FUNCFLAG_FHIDDEN", "FUNCFLAG_FIMMEDIATEBIND",
    "FUNCFLAG_FNONBROWSABLE", "FUNCFLAG_FREPLACEABLE", "FUNCFLAG_FREQUESTEDIT",
    "FUNCFLAG_FRESTRICTED", "FUNCFLAG_FSOURCE", "FUNCFLAG_FUIDEFAULT",
    "FUNCFLAG_FUSESGETLASTERROR", "FUNCFLAGS", "tagFUNCFLAGS", "FUNCKIND",
    "tagFUNCKIND", "GetRecordInfoFromGuids", "GetRecordInfoFromTypeInfo",
    "HREFTYPE", "ICreateTypeInfo", "ICreateTypeLib", "ICreateTypeLib2",
    "IDLDESC", "tagIDLDESC", "IMPLTYPEFLAG_FDEFAULT",
    "IMPLTYPEFLAG_FDEFAULTVTABLE", "IMPLTYPEFLAG_FRESTRICTED",
    "IMPLTYPEFLAG_FSOURCE", "IProvideClassInfo", "IProvideClassInfo2",
    "IRecordInfo", "ITypeComp", "ITypeInfo", "ITypeLib", "LoadRegTypeLib",
    "LoadTypeLib", "LoadTypeLibEx", "LPPARAMDESCEX", "MEMBERID",
    "N10tagVARDESC5DOLLAR_205E", "N11tagELEMDESC5DOLLAR_204E",
    "N11tagTYPEDESC5DOLLAR_203E", "OLECHAR", "PARAMDESC", "tagPARAMDESC",
    "tagPARAMDESCEX", "PARAMFLAG_FHASCUSTDATA", "PARAMFLAG_FHASDEFAULT",
    "PARAMFLAG_FIN", "PARAMFLAG_FLCID", "PARAMFLAG_FOPT", "PARAMFLAG_FOUT",
    "PARAMFLAG_FRETVAL", "PARAMFLAG_NONE", "PVOID", "QueryPathOfRegTypeLib",
    "RegisterTypeLib", "REGKIND", "tagREGKIND", "REGKIND_DEFAULT",
    "REGKIND_NONE", "REGKIND_REGISTER", "SAFEARRAYBOUND", "tagSAFEARRAYBOUND",
    "SYS_MAC", "SYS_WIN16", "SYS_WIN32", "SYS_WIN64", "SYSKIND", "tagSYSKIND",
    "TKIND_ALIAS", "TKIND_COCLASS", "TKIND_DISPATCH", "TKIND_ENUM",
    "TKIND_INTERFACE", "TKIND_MAX", "TKIND_MODULE", "TKIND_RECORD",
    "TKIND_UNION", "tagTLIBATTR", "TLIBATTR", "tagTYPEATTR", "TYPEATTR",
    "tagTYPEDESC", "TYPEDESC", "TYPEFLAG_FAGGREGATABLE", "TYPEFLAG_FAPPOBJECT",
    "TYPEFLAG_FCANCREATE", "TYPEFLAG_FCONTROL", "TYPEFLAG_FDISPATCHABLE",
    "TYPEFLAG_FDUAL", "TYPEFLAG_FHIDDEN", "TYPEFLAG_FLICENSED",
    "TYPEFLAG_FNONEXTENSIBLE", "TYPEFLAG_FOLEAUTOMATION",
    "TYPEFLAG_FPREDECLID", "TYPEFLAG_FPROXY", "TYPEFLAG_FREPLACEABLE",
    "TYPEFLAG_FRESTRICTED", "TYPEFLAG_FREVERSEBIND", "TYPEFLAGS",
    "tagTYPEFLAGS", "TYPEKIND", "tagTYPEKIND", "ULONG_PTR",
    "UnRegisterTypeLib", "VAR_CONST", "VAR_DISPATCH", "VAR_PERINSTANCE",
    "VAR_STATIC", "VARDESC", "tagVARDESC", "VARFLAG_FBINDABLE",
    "VARFLAG_FDEFAULTBIND", "VARFLAG_FDEFAULTCOLLELEM", "VARFLAG_FDISPLAYBIND",
    "VARFLAG_FHIDDEN", "VARFLAG_FIMMEDIATEBIND", "VARFLAG_FNONBROWSABLE",
    "VARFLAG_FREADONLY", "VARFLAG_FREPLACEABLE", "VARFLAG_FREQUESTEDIT",
    "VARFLAG_FRESTRICTED", "VARFLAG_FSOURCE", "VARFLAG_FUIDEFAULT",
    "VARFLAGS", "tagVARFLAGS", "VARKIND", "tagVARKIND",
]
# fmt: on
