#ifndef __ATLB_COM_INC__
#define __ATLB_COM_INC__

#ifndef CLSCTX_INPROC_SERVER
#define CLSCTX_INPROC_SERVER              0x1
#endif
#ifndef CLSCTX_INPROC_HANDLER
#define CLSCTX_INPROC_HANDLER             0x2
#endif
#ifndef CLSCTX_LOCAL_SERVER
#define CLSCTX_LOCAL_SERVER               0x4
#endif
#ifndef CLSCTX_INPROC_SERVER16
#define CLSCTX_INPROC_SERVER16            0x8
#endif
#ifndef CLSCTX_REMOTE_SERVER
#define CLSCTX_REMOTE_SERVER              0x10
#endif
#ifndef CLSCTX_INPROC_HANDLER16
#define CLSCTX_INPROC_HANDLER16           0x20
#endif
#ifndef CLSCTX_RESERVED1
#define CLSCTX_RESERVED1                  0x40
#endif
#ifndef CLSCTX_RESERVED2
#define CLSCTX_RESERVED2                  0x80
#endif
#ifndef CLSCTX_RESERVED3
#define CLSCTX_RESERVED3                  0x100
#endif
#ifndef CLSCTX_RESERVED4
#define CLSCTX_RESERVED4                  0x200
#endif
#ifndef CLSCTX_NO_CODE_DOWNLOAD
#define CLSCTX_NO_CODE_DOWNLOAD           0x400
#endif
#ifndef CLSCTX_RESERVED5
#define CLSCTX_RESERVED5                  0x800
#endif
#ifndef CLSCTX_NO_CUSTOM_MARSHAL
#define CLSCTX_NO_CUSTOM_MARSHAL          0x1000
#endif
#ifndef CLSCTX_ENABLE_CODE_DOWNLOAD
#define CLSCTX_ENABLE_CODE_DOWNLOAD       0x2000
#endif
#ifndef CLSCTX_NO_FAILURE_LOG
#define CLSCTX_NO_FAILURE_LOG             0x4000
#endif
#ifndef CLSCTX_DISABLE_AAA
#define CLSCTX_DISABLE_AAA                0x8000
#endif
#ifndef CLSCTX_ENABLE_AAA
#define CLSCTX_ENABLE_AAA                 0x10000
#endif
#ifndef CLSCTX_FROM_DEFAULT_CONTEXT
#define CLSCTX_FROM_DEFAULT_CONTEXT       0x20000
#endif
#ifndef CLSCTX_ACTIVATE_32_BIT_SERVER
#define CLSCTX_ACTIVATE_32_BIT_SERVER     0x40000
#endif
#ifndef CLSCTX_ACTIVATE_64_BIT_SERVER
#define CLSCTX_ACTIVATE_64_BIT_SERVER     0x80000
#endif
#ifndef CLSCTX_INPROC
#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER)
#endif
#ifndef CLSCTX_SERVER
#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
#endif
#ifndef CLSCTX_ALL
#define CLSCTX_ALL    (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
#endif

#ifndef VARIANT_TRUE
#define VARIANT_TRUE  -1
#endif
#ifndef VARIANT_FALSE
#define VARIANT_FALSE  0
#endif

#ifndef GUID
struct GUID,1
{
   unsigned int data1;
   unsigned word data2;
   unsigned word data3;
   unsigned byte data4[8];
}
#endif

#ifndef DECIMAL_NEG
#define DECIMAL_NEG 0x80
#endif

#ifndef DECIMAL
struct DECIMAL
{
   unsigned word wReserved;
   unsigned byte scale;       // The number of decimal places for the number.
                              // Valid values are from 0 to 28. So 12.345 is represented
                              // as 12345 with a scale of 3.
   unsigned byte sign;        // 0 for positive numbers or %DECIMAL_NEG (&H80) for
                              // negative numbers. So -1 is represented as
                              // 1 with the %DECIMAL_NEG bit set.
   unsigned int Hi32;         // The high 32 bits of your number
   int64 Lo64;                // The low 64 bits of your number.
}
#endif

#ifndef CY
struct CY
{
   unsigned int Lo;
   int Hi;
}
#endif

#ifndef BRECORD
struct BRECORD
{
   unsigned int pvRecord;
   pointer *pRecInfo;   // IRecordInfo
}
#endif

#ifndef VARIANT
struct VARIANT,1
{
   unsigned word vt;                    // VARTYPE
   unsigned word wReserved1;
   unsigned word wReserved2;
   unsigned word wReserved3;
   union
   {
      int64          llVal;            // VT_I8
      int            lVal;             // VT_I4
      unsigned byte  bVal;             // VT_UI1
      word           iVal;             // VT_I2
      float          fltVal;           // VT_R4
      double         dblVal;           // VT_R8
      word           boolVal;          // VT_BOOL
      word           bool;             // VT_BOOL
      int            scode;            // VT_ERROR
      CY             cyVal;            // VT_CY
      double         date;             // VT_DATE
      pointer        bstrVal;          // VT_BSTR
      pointer        punkVal;          // VT_UNKNOWN
      pointer        pdispVal;         // VT_DISPATCH
      pointer        parray;           // VT_ARRAY
      pointer        pbVal;            // VT_BYREF|VT_UI1
      pointer        piVal;            // VT_BYREF|VT_I2
      pointer        plVal;            // VT_BYREF|VT_I4
      pointer        pllVal;           // VT_BYREF|VT_I8
      pointer        pfltVal;          // VT_BYREF|VT_R4
      pointer        pdblVal;          // VT_BYREF|VT_R8
      pointer        pboolVal;         // VT_BYREF|VT_BOOL
      pointer        pbool;            // VT_BYREF|VT_BOOL
      pointer        pscode;           // VT_BYREF|VT_ERROR
      pointer        pcyVal;           // VT_BYREF|VT_CY
      pointer        pdate;            // VT_BYREF|VT_DATE
      pointer        pbstrVal;         // VT_BYREF|VT_BSTR
      pointer        ppunkVal;         // VT_BYREF|VT_UNKNOWN
      pointer        ppdispVal;        // VT_BYREF|VT_DISPATCH
      pointer        pparray;          // VT_BYREF|VT_ARRAY
      pointer        pvarVal;          // VT_BYREF|VT_VARIANT
      pointer        pByRef;           // Generic BYREF (void*)
      byte           cVal;             // VT_I1
      unsigned word  uiVal;            // VT_UI2
      unsigned int   ulVal;            // VT_UI4
      unsigned int64 ullVal;           // VT_UI8
      int            intVal;           // VT_INT
      unsigned int   uintVal;          // VT_UINT
      pointer        pdecVal;          // VT_BYREF|VT_DECIMAL
      pointer        pcVal;            // VT_BYREF|VT_I1
      pointer        puiVal;           // VT_BYREF|VT_UI2
      pointer        pulVal;           // VT_BYREF|VT_UI4
      pointer        pullVal;          // VT_BYREF|VT_UI8
      pointer        pintVal;          // VT_BYREF|VT_INT
      pointer        puintVal;         // VT_BYREF|VT_UINT
      BRECORD        br;               // VT_RECORD
   }
}
#endif

import void VariantInit(VARIANT *pvarg);
import int VariantClear(VARIANT *pvarg);
import int VariantChangeType(VARIANT *pvargDest, VARIANT *pvarSrc, unsigned word wFlags, unsigned word vt);
import int VariantChangeTypeEx(VARIANT *pvargDest, VARIANT *pvarSrc, int lcid, unsigned word wFlags, unsigned word vt);
import int VariantCopy(VARIANT *pvargDest, VARIANT *pvarSrc);
import int VariantCopyInd(VARIANT *pvargDest, VARIANT *pvarSrc);

#ifndef DISPPARAMS
struct DISPPARAMS
{
   VARIANT       *rgvarg;               // Array of arguments.
   int           *rgdispidNamedArgs;    // Dispatch IDs of named arguments.
   unsigned int  cArgs;                 // Number of arguments.
   unsigned int  cNamedArgs;            // Number of named arguments.
}
#endif

#ifndef EXCEPINFO
struct EXCEPINFO
{
   unsigned word wCode;                 // An error code describing the error.
   unsigned word wReserved;             // Reserved; should be set to 0
   pointer       bstrSource;            // BSTR - Source of the exception.
   pointer       bstrDescription;       // BSTR - Textual description of the error.
   pointer       bstrHelpFile;          // BSTR - Help file path.
   unsigned int  dwHelpContext;         // Help context ID.
   pointer       pvReserved;            // Must be set to NULL
   pointer       pfnDeferredFillIn;     // Pointer to function that fills in Help and description info
   int           scode;                 // An SCODE value describing the error.
}
#endif

import int MultiByteToWideChar(
   unsigned int CodePage,          // code page
   unsigned int dwFlags,           // character-type options
   unsigned byte *lpMultiByteStr,  // string to map
   int cbMultiByte,                // number of bytes in string
   unsigned word *lpWideCharStr,   // wide-character buffer
   int cchWideChar                 // size of buffer
);

import int WideCharToMultiByte(
   unsigned int CodePage,            // code page
   unsigned int dwFlags,             // performance and mapping flags
   unsigned word *lpWideCharStr,     // wide-character string
   int cchWideChar,                  // number of chars in string.
   unsigned byte *lpMultiByteStr,    // buffer for new string
   int cbMultiByte,                  // size of buffer
   unsigned byte *lpDefaultChar,     // default for unmappable chars
   unsigned int *lpUsedDefaultChar   // set when default char used
);

import void RtlZeroMemory(void *Destination, unsigned int Length);
import void memcpy(void *dest, void *src, unsigned int num);
import int lstrlenW(unsigned word *lpwcs);
import int CLSIDFromString(unsigned word *lpsz, GUID *pclsid);
import int StringFromCLSID(GUID *rclsid, unsigned int *ppsz);
import int StringFromGUID2(GUID *rclsid, unsigned word *lpsz, int cchMax);
import int IsEqualGUID(GUID *rguid1, GUID *rguid2);

sub _CLSIDFromString (string psz), GUID
{
   int hr;
   GUID rclsid;
   int nLen;
   pointer pwcs;

   nLen = (len(psz) + 1) * 2;
   pwcs = AllocHeap(nLen);
   RtlZeroMemory(pwcs, nLen);
   hr = MultiByteToWideChar(0, 0, psz, len(psz), pwcs, nLen);
   hr = CLSIDFromString(pwcs, rclsid);
   FreeHeap(pwcs);
   return rclsid;
}

sub _StringFromGUID2 (GUID *rclsid), string
{
   int hr;
   string pwsz;
   string psz;
   hr = StringFromGUID2(rclsid, pwsz, 40);
   if hr = 0 return "";
   hr = WideCharToMultiByte(0, 0, pwsz, -1, psz, 255, 0, 0);
   return psz;
}


import int CoInitialize(void *pvReserved);
import void CoUninitialize();
import int CoCreateInstance(GUID *rclsid, pointer pUnkOuter, unsigned int dwClsContext, GUID *riid, void *ppv);
import void CoTaskMemFree(void *pv);

import pointer SysAllocString(pointer *sz);
import pointer SysAllocStringByteLen(string *psz, unsigned int nLen);
import pointer SysAllocStringLen(pointer *pch, unsigned int cch);
import void SysFreeString(pointer *bstr);
import int SysReAllocString(pointer *pbstr, pointer *psz);
import int SysReAllocStringLen(pointer *pbstr, pointer *psz, unsigned int cch);
import unsigned int SysStringLen(pointer *bstr);
import unsigned int SysStringByteLen(pointer *bstr);

sub BStrToAnsi (pointer *bstr), string
{
   int nLen;
   pointer psz;

   if (bstr = null) return "";
   nLen = SysStringLen(bstr);
   if (nLen = 0) return "";
   nLen = (nLen + 1) * 2;
   psz = AllocHeap(nLen);
   memcpy(psz, bstr, nLen);
   psz = w2s(*(string)psz);
   return psz;
}

sub BStrToChar (pointer *bstr), string
{
   int nLen;
   pointer psz;

   if (bstr = null) return "";
   nLen = SysStringLen(bstr);
   if (nLen = 0) return "";
   nLen = (nLen + 1) * 2;
   psz = AllocHeap(nLen);
   memcpy(psz, bstr, nLen);
   return psz;
}

sub DEFINE_GUID(GUID *rguid, unsigned int data1, unsigned word data2, unsigned word data3, unsigned byte c1, unsigned byte c2, unsigned byte c3, unsigned byte c4, unsigned byte c5, unsigned byte c6, unsigned byte c7, unsigned byte c8)
{
   if (rguid != null)
   {
      rguid->data1 = data1;
      rguid->data2 = data2;
      rguid->data3 = data3;
      rguid->data4[0] = c1;
      rguid->data4[1] = c2;
      rguid->data4[2] = c3;
      rguid->data4[3] = c4;
      rguid->data4[4] = c5;
      rguid->data4[5] = c6;
      rguid->data4[6] = c7;
      rguid->data4[7] = c8;
   }
   return;
}

extern _IID_IUnknown as GUID;
// {00000000-0000-0000-C000-000000000046}
interface IUnknown
{
   declare virtual QueryInterface(GUID *riid, void *ppvObject), int;
   declare virtual AddRef(), unsigned int;
   declare virtual Release(), unsigned int;
}

extern _IID_IDispatch as GUID;
// {00020400-0000-0000-C000-000000000046}
interface IDispatch : IUnknown
{
   declare virtual GetTypeInfoCount(unsigned int *pctinfo), int;
   declare virtual GetTypeInfo(unsigned int iTInfo, int lcid, pointer *ppTInfo), int;
   declare virtual GetIDsOfNames(GUID *riid, unsigned word *rgszNames, unsigned int cNames, int lcid, int *rgDispID), int;
   declare virtual Invoke(int dispIdMember, GUID *riid, int lcid, unsigned word wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, unsigned int *puArgErr), int;
}

extern _IID_IEnumVARIANT as GUID;
// {00020404-0000-0000-C000-000000000046}
interface IEnumVARIANT : IUnknown
{
   declare virtual Next(unsigned int celt, VARIANT *rgvar, unsigned int *pceltFetched), int;
   declare virtual Skip(unsigned int celt), int;
   declare virtual Reset(), int;
   declare virtual Clone(IEnumVARIANT *ppenum), int;
}

extern _IID_IClassFactory as GUID;
// {00000001-0000-0000-C000-000000000046}
interface IClassFactory : IUnknown
{
   declare virtual CreateInstance(IUnknown *pUnkOuter, GUID * riid, void *ppvObject), int;
   declare virtual LockServer(int fLock), int;
}

struct LICINFO
{
   int cbLicInfo;
   int fRuntimeKeyAvail;
   int fLicVerified;
}

extern _IID_IClassFactory2 as GUID;
// {B196B28F-BAB4-101A-B69C-00AA00341D07}
interface IClassFactory2 : IClassFactory
{
   declare virtual GetLicInfo(LICINFO *pLicInfo), int;
   declare virtual RequestLicKey(unsigned int dwReserved, pointer *pBstrKey), int;
   declare virtual CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, GUID *riid, pointer bstrKey, void * ppvObj), int;
}


struct CONNECTDATA
{
   IUnknown *pUnk;
   unsigned int dwCookie;
}

extern _IID_IEnumConnections as GUID;
// {B196B287-BAB4-101A-B69C-00AA00341D07}
interface IEnumConnections : IUnknown
{
   declare virtual Next(unsigned int cConnections, CONNECTDATA *rgcd, unsigned int *pcFetched), int;
   declare virtual Skip(unsigned int cConnections), int;
   declare virtual Reset(), int;
   declare virtual Clone(IEnumConnections *ppEnum), int;
}

extern _IID_IConnectionPoint as GUID;
// {B196B286-BAB4-101A-B69C-00AA00341D07}
interface IConnectionPoint : IUnknown
{
   declare virtual GetConnectionInterface(GUID *pIID), int;
   declare virtual GetConnectionPointContainer(IConnectionPointContainer *ppCPC), int;
   declare virtual Advise(IUnknown *pUnkSink, unsigned int *pdwCookie), int;
   declare virtual Unadvise(unsigned int dwCookie), int;
   declare virtual EnumConnections(IEnumConnections *ppEnum), int;
}

extern _IID_IEnumConnectionPoints as GUID;
// {B196B285-BAB4-101A-B69C-00AA00341D07}
interface IEnumConnectionPoints : IUnknown
{
   declare virtual Next(unsigned int celt, pointer *rgelt, unsigned int pceltFetched), int;
   declare virtual Skip(unsigned int celt), int;
   declare virtual Reset(), int;
   declare virtual Clone(IEnumConnectionPoints *ppEnum), int;
}

extern _IID_IConnectionPointContainer as GUID;
// {B196B284-BAB4-101A-B69C-00AA00341D07}
interface IConnectionPointContainer : IUnknown
{
   declare virtual EnumConnectionPoints(IEnumConnectionPoints *ppEnum), int;
   declare virtual FindConnectionPoint(GUID *riid, IConnectionPoint *ppCP), int;
}

SUB EventsAdvise(IUnknown *pUnkCP, IUnknown *pUnk, GUID *iid, unsigned int *pdw), int
{
   if (pUnkCP = null)
      return 0x80070057;  // E_INVALIDARG
   IConnectionPointContainer *pCPC = null;
   IConnectionPoint *pCP = null;
   int hr = 0;
   hr = pUnkCP->QueryInterface(_IID_IConnectionPointContainer, &pCPC);
   if (hr = 0)
      hr = pCPC->FindConnectionPoint(iid, &pCP);
   if (hr = 0)
      hr = pCP->Advise(punk, &pdw);
   return hr;
}

SUB EventsUnadvise(IUnknown *pUnkCP, GUID *iid, unsigned int dw), int
{
   if (pUnkCP = null)
      return 0x80070057;  // E_INVALIDARG
   IConnectionPointContainer *pCPC = null;
   IConnectionPoint *pCP = null;
   int hr = 0;
   hr = pUnkCP->QueryInterface(_IID_IConnectionPointContainer, &pCPC);
   if (hr = 0)
      hr = pCPC->FindConnectionPoint(iid, &pCP);
   if (hr = 0)
      hr = pCP->Unadvise(dw);
   return hr;
}

#endif
