script_com.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #pragma once
  2. extern bool g_ComErrorNotify;
  3. class ComObject;
  4. class ComEvent : public ObjectBase
  5. {
  6. DWORD mCookie = 0;
  7. ComObject *mObject;
  8. ITypeInfo *mTypeInfo = nullptr;
  9. IID mIID;
  10. IObject *mAhkObject = nullptr;
  11. ScriptModule *mModule = nullptr;
  12. TCHAR mPrefix[64];
  13. public:
  14. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  15. STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
  16. STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
  17. // IObject::Invoke() and Type() are unlikely to be called, since that would mean
  18. // the script has a reference to the object, which means either that the script
  19. // itself has implemented IConnectionPoint (and why would it?), or has used the
  20. // IEnumConnections interface to retrieve its own object (unlikely).
  21. //ResultType Invoke(IObject_Invoke_PARAMS_DECL); // ObjectBase::Invoke is sufficient.
  22. IObject_Type_Impl("ComEvent") // Unlikely to be called; see above.
  23. Object *Base() { return nullptr; }
  24. HRESULT Connect(ITypeInfo *tinfo = nullptr, IID *iid = nullptr);
  25. void SetPrefixOrSink(LPCTSTR pfx, IObject *ahkObject);
  26. ComEvent(ComObject *obj) : mObject(obj) { }
  27. ~ComEvent();
  28. friend class ComObject;
  29. };
  30. class ComObject : public ObjectBase
  31. {
  32. public:
  33. union
  34. {
  35. IDispatch *mDispatch;
  36. IUnknown *mUnknown;
  37. SAFEARRAY *mArray;
  38. void *mValPtr;
  39. __int64 mVal64; // Allow 64-bit values when ComObject is used as a VARIANT in 32-bit builds.
  40. };
  41. ComEvent *mEventSink;
  42. VARTYPE mVarType;
  43. enum { F_OWNVALUE = 1 };
  44. USHORT mFlags;
  45. enum
  46. {
  47. P_Ptr,
  48. // ComValueRef
  49. P___Item, // v2.0: Allows accessing a VT_BYREF value via comobj[].
  50. P___Value = P___Item, // v2.1: Alias to allow use with VAR_VIRTUAL_OBJ (ByRef parameters).
  51. };
  52. static ObjectMember sRefMembers[], sValueMembers[];
  53. static ObjectMemberMd sArrayMembers[];
  54. FResult SafeArray_Item(VariantParams &aParam, ExprTokenType *aNewValue, ResultToken *aResultToken);
  55. FResult set_SafeArray_Item(ExprTokenType &aNewValue, VariantParams &aParam) { return SafeArray_Item(aParam, &aNewValue, nullptr); }
  56. FResult get_SafeArray_Item(ResultToken &aResultToken, VariantParams &aParam) { return SafeArray_Item(aParam, nullptr, &aResultToken); }
  57. FResult SafeArray_Clone(IObject *&aRetVal);
  58. FResult SafeArray_Enum(optl<int>, IObject *&aRetVal);
  59. FResult SafeArray_MaxIndex(optl<UINT> aDims, int &aRetVal);
  60. FResult SafeArray_MinIndex(optl<UINT> aDims, int &aRetVal);
  61. ResultType Invoke(IObject_Invoke_PARAMS_DECL);
  62. void Invoke(ResultToken &aResultToken, int aID, int aFlags, ExprTokenType *aParam[], int aParamCount);
  63. LPTSTR Type();
  64. Object *Base();
  65. IObject_DebugWriteProperty_Def;
  66. void ToVariant(VARIANT &aVar)
  67. {
  68. aVar.vt = mVarType;
  69. aVar.llVal = mVal64;
  70. // Caller handles this if needed:
  71. //if (VT_DISPATCH == mVarType && mDispatch)
  72. // mDispatch->AddRef();
  73. }
  74. ComObject(IDispatch *pdisp)
  75. : mVal64((__int64)pdisp), mVarType(VT_DISPATCH), mEventSink(NULL), mFlags(0) { }
  76. ComObject(__int64 llVal, VARTYPE vt, USHORT flags = 0)
  77. : mVal64(llVal), mVarType(vt), mEventSink(NULL), mFlags(flags) { }
  78. ~ComObject()
  79. {
  80. if ((VT_DISPATCH == mVarType || VT_UNKNOWN == mVarType) && mUnknown)
  81. {
  82. if (mEventSink)
  83. {
  84. mEventSink->Connect(FALSE);
  85. if (mEventSink) // i.e. it wasn't fully released as a result of calling Unadvise().
  86. mEventSink->mObject = nullptr;
  87. }
  88. mUnknown->Release();
  89. }
  90. else if ((mVarType & (VT_BYREF|VT_ARRAY)) == VT_ARRAY && (mFlags & F_OWNVALUE))
  91. {
  92. SafeArrayDestroy(mArray);
  93. }
  94. else if (mVarType == VT_BSTR && (mFlags & F_OWNVALUE))
  95. {
  96. SysFreeString((BSTR)mValPtr);
  97. }
  98. }
  99. };
  100. class ComEnum : public EnumBase
  101. {
  102. IEnumVARIANT *penum;
  103. bool cheat;
  104. public:
  105. ResultType Next(Var *aOutput, Var *aOutputType);
  106. ComEnum(IEnumVARIANT *enm);
  107. ~ComEnum()
  108. {
  109. penum->Release();
  110. }
  111. };
  112. class ComArrayEnum : public EnumBase
  113. {
  114. ComObject *mArrayObject;
  115. void *mData;
  116. long mLBound, mUBound;
  117. UINT mElemSize;
  118. VARTYPE mType;
  119. bool mIndexMode;
  120. long mOffset = -1;
  121. ComArrayEnum(ComObject *aObj, void *aData, long aLBound, long aUBound, UINT aElemSize, VARTYPE aType, bool aIndexMode)
  122. : mArrayObject(aObj), mData(aData), mLBound(aLBound), mUBound(aUBound), mElemSize(aElemSize), mType(aType), mIndexMode(aIndexMode)
  123. {
  124. }
  125. public:
  126. static HRESULT Begin(ComObject *aArrayObject, ComArrayEnum *&aOutput, int aMode);
  127. ResultType Next(Var *aVar1, Var *aVar2);
  128. ~ComArrayEnum();
  129. };
  130. // Adapts an AutoHotkey enumerator object to the IEnumVARIANT COM interface.
  131. class EnumComCompat : public IEnumVARIANT, public IServiceProvider
  132. {
  133. IObject *mEnum;
  134. int mRefCount;
  135. bool mCheat;
  136. public:
  137. EnumComCompat(IObject *enumObj) : mEnum(enumObj), mRefCount(1), mCheat(false) {}
  138. ~EnumComCompat() { mEnum->Release(); }
  139. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
  140. STDMETHODIMP_(ULONG) AddRef();
  141. STDMETHODIMP_(ULONG) Release();
  142. STDMETHODIMP Next(ULONG celt, /*out*/ VARIANT *rgVar, /*out*/ ULONG *pCeltFetched);
  143. STDMETHODIMP Skip(ULONG celt);
  144. STDMETHODIMP Reset();
  145. STDMETHODIMP Clone(/*out*/ IEnumVARIANT **ppEnum);
  146. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
  147. };
  148. enum TTVArgType
  149. {
  150. VariantIsValue,
  151. VariantIsAllocatedString,
  152. VariantIsVarRef
  153. };
  154. void TokenToVariant(ExprTokenType &aToken, VARIANT &aVar, TTVArgType *aVarIsArg = FALSE);
  155. HRESULT TokenToVarType(ExprTokenType &aToken, VARTYPE aVarType, void *apValue, bool aCallerIsComValue = false);
  156. void ComError(HRESULT, ResultToken &, LPTSTR = _T(""), EXCEPINFO* = NULL);
  157. bool SafeSetTokenObject(ExprTokenType &aToken, IObject *aObject);