module external.directx.com;

public import core.sys.windows.com;
public import external.directx.win32;

alias REFGUID = const(GUID)*;
alias REFIID = const(GUID)*;
alias REFCLSID = const(GUID)*;
alias REFFMTID = const(GUID)*;

//mixin(uuid!(IUnknown, "00000000-0000-0000-C000-000000000046"));
mixin(uuid!(IUnknown, "00000000", "0000", "0000", ["C0", "00", "00", "00", "00", "00", "00", "46"]));
mixin(uuid!(IClassFactory, "00000001", "0000", "0000", ["C0", "00", "00", "00", "00", "00", "00", "46"]));

mixin(uuid!(ISequentialStream, "0C733A30", "2A1C", "11CE", ["AD", "E5", "00", "AA", "00", "44", "77", "3D"]));
public interface ISequentialStream : IUnknown
{
extern (Windows):
    HRESULT Read(void* pv, ULONG cb, ULONG* pcbRead);
    HRESULT Write(const void* pv, ULONG cb, ULONG* pcbWritten);
}

mixin(uuid!(IStream, "0C733A30", "2A1C", "11CE", ["AD", "E5", "00", "AA", "00", "44", "77", "3D"]));
public interface IStream : ISequentialStream
{
extern (Windows):
    HRESULT Clone(IStream** ppstm);
    HRESULT Commit(uint grfCommitFlags);
    HRESULT CopyTo(IStream pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten);
    HRESULT LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, uint dwLockType);
    HRESULT Revert();
    HRESULT Seek(LARGE_INTEGER dlibMove, uint dwOrigin, ULARGE_INTEGER* plibNewPosition);
    HRESULT SetSize(ULARGE_INTEGER libNewSize);
    HRESULT Stat(STATSTG* pstatstg, uint grfStatFlag);
    HRESULT UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, uint dwLockType);
}

mixin(uuid!(IPrintDocumentPackageTarget, "1b8efec4", "3019", "4c27", ["96", "4e", "36", "72", "02", "15", "69", "06"]));
public interface IPrintDocumentPackageTarget : IUnknown
{
extern (Windows):
    HRESULT Cancel();
    HRESULT GetPackageTarget(GUID* guidTargetType, IID* riid, void** ppvTarget);
    HRESULT GetPackageTargetTypes(uint* targetCount, GUID* targetTypes);
}

mixin(uuid!(IEnumUnknown, "00000100", "0000", "0000", ["C0", "00", "00", "00", "00", "00", "00", "46"]));
public interface IEnumUnknown : IUnknown
{
extern (Windows):
    HRESULT Clone(IEnumUnknown** ppenum);
    HRESULT Next(ulong celt, IUnknown* rgelt, ulong* pceltFetched);
    HRESULT Reset();
    HRESULT Skip(ulong celt);
}

mixin(uuid!(IEnumString, "00000101", "0000", "0000", ["C0", "00", "00", "00", "00", "00", "00", "46"]));
public interface IEnumString : IUnknown
{
extern (Windows):
    HRESULT Clone(IEnumString** ppenum);
    HRESULT Next(ulong celt, LPOLESTR* rgelt, ulong* pceltFetched);
    HRESULT Reset();
    HRESULT Skip(ulong celt);
}

template uuid(T, const char[] g)
{
    const char[] uuid = "const IID IID_" ~ T.stringof ~ "={ 0x" ~ g[0 .. 8] ~ ",0x" ~ g[9 .. 13] ~ ",0x" ~ g[14 .. 18] ~ ",[0x" ~ g[19 .. 21] ~ ",0x" ~ g[21 .. 23] ~ ",0x" ~ g[24 .. 26] ~ ",0x" ~ g[26 .. 28] ~ ",0x" ~ g[28 .. 30] ~ ",0x" ~ g[30 .. 32] ~ ",0x" ~ g[32 .. 34] ~ ",0x" ~ g[34 .. 36] ~ "]};" ~ "template uuidof(T:" ~ T.stringof ~ "){" ~ "    const IID uuidof ={ 0x" ~ g[0 .. 8] ~ ",0x"
        ~ g[9 .. 13] ~ ",0x" ~ g[14 .. 18] ~ ",[0x" ~ g[19 .. 21] ~ ",0x" ~ g[21 .. 23] ~ ",0x" ~ g[24 .. 26] ~ ",0x" ~ g[26 .. 28] ~ ",0x" ~ g[28 .. 30] ~ ",0x" ~ g[30 .. 32] ~ ",0x" ~ g[32 .. 34] ~ ",0x" ~ g[34 .. 36] ~ "]};" ~ "}";
}

template uuid(T, string data1, string data2, string data3, string[8] data4)
{
    const char[] uuid = "const IID IID_" ~ T.stringof ~ "={ 0x" ~ data1 ~ ",0x" ~ data2 ~ ",0x" ~ data3 ~ ",[0x" ~ data4[0] ~ ",0x" ~ data4[1] ~ ",0x" ~ data4[2] ~ ",0x" ~ data4[3] ~ ",0x" ~ data4[4] ~ ",0x" ~ data4[5] ~ ",0x" ~ data4[6] ~ ",0x" ~ data4[7] ~ "]};" ~ "template uuidof(T:" ~ T.stringof ~ "){" ~ "    const IID uuidof ={ 0x" ~ data1 ~ ",0x" ~ data2 ~ ",0x" ~ data3 ~ ",[0x" ~ data4[0] ~ ",0x"
        ~ data4[1] ~ ",0x" ~ data4[2] ~ ",0x" ~ data4[3] ~ ",0x" ~ data4[4] ~ ",0x" ~ data4[5] ~ ",0x" ~ data4[6] ~ ",0x" ~ data4[7] ~ "]};" ~ "}";
}

// from intsafe.h
enum INTSAFE_E_ARITHMETIC_OVERFLOW = cast(HRESULT) 0x80070216L; // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW

public class DXPtr(T : IUnknown)
{
    private T _value = null;
    public @property T value()
    {
        return _value;
    }

    alias value this;
    public this(T value)
    {
        _value = value;
    }

    public void opAssign(T value)
    {
        if (_value !is null)
        {
            _value.Release();
            _value = value;
        }
        else
        {
            _value = value;
        }
    }

    public ~this()
    {
        if (_value !is null)
        {
            _value.Release();
            _value = null;
        }
    }
}

public struct SIZE
{
    long X;
    long Y;
}

struct FILETIME
{
    uint dwLowDateTime;
    uint dwHighDateTime;
}

struct FONTSIGNATURE
{
    int[4] fsUsb;
    int[2] fsCsb;
}

public struct STATSTG
{
    LPOLESTR pwcsName;
    DWORD type;
    ULARGE_INTEGER cbSize;
    FILETIME mtime;
    FILETIME ctime;
    FILETIME atime;
    DWORD grfMode;
    DWORD grfLocksSupported;
    CLSID clsid;
    DWORD grfStateBits;
    DWORD reserved;
}