diff --git a/CWeChatRobot/ForwardMessage.cpp b/CWeChatRobot/ForwardMessage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ceed05a944665dcc527c3458f732ee0290d586c7 --- /dev/null +++ b/CWeChatRobot/ForwardMessage.cpp @@ -0,0 +1,30 @@ +#include "pch.h" + +struct ForwardMessageStruct +{ + DWORD wxid; + DWORD localId; +}; + +BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId) +{ + WeChatProcess hp(pid); + if (!hp.m_init) + return 1; + DWORD ForwardMessageRemoteAddr = hp.GetProcAddr(ForwardMessageRemote); + if (ForwardMessageRemoteAddr == 0) + { + return 1; + } + ForwardMessageStruct params = {0}; + WeChatData r_wxid(hp.GetHandle(), wxid, TEXTLENGTH(wxid)); + params.wxid = (DWORD)r_wxid.GetAddr(); + params.localId = localId; + WeChatData r_params(hp.GetHandle(), ¶ms, sizeof(params)); + if (!params.wxid || !r_params.GetAddr()) + { + return 1; + } + DWORD dwRet = CallRemoteFunction(hp.GetHandle(), ForwardMessageRemoteAddr, r_params.GetAddr()); + return dwRet == 0; +} diff --git a/CWeChatRobot/ForwardMessage.h b/CWeChatRobot/ForwardMessage.h new file mode 100644 index 0000000000000000000000000000000000000000..ec56a9ec26410d9ce3074941aed50b0d62a020a4 --- /dev/null +++ b/CWeChatRobot/ForwardMessage.h @@ -0,0 +1,4 @@ +#pragma once +#include + +BOOL ForwardMessage(DWORD pid, wchar_t *wxid, int localId); diff --git a/CWeChatRobot/WeChatRobot.cpp b/CWeChatRobot/WeChatRobot.cpp index 9053deb5fb59c693e9b4e50ff9582ff84693e549..9321dc7c474e0711fc9858d076c4521732149d24 100644 --- a/CWeChatRobot/WeChatRobot.cpp +++ b/CWeChatRobot/WeChatRobot.cpp @@ -5,9 +5,9 @@ // CWeChatRobot /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CStartRobotService(DWORD pid, int *__result) { *__result = StartRobotService(pid); @@ -15,9 +15,9 @@ STDMETHODIMP CWeChatRobot::CStartRobotService(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CStopRobotService(DWORD pid, int *__result) { *__result = StopRobotService(pid); @@ -25,11 +25,11 @@ STDMETHODIMP CWeChatRobot::CStopRobotService(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:文本消息内容 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:文本消息内容 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendText(DWORD pid, BSTR wxid, BSTR wxmsg, int *__result) { *__result = SendText(pid, wxid, wxmsg); @@ -37,12 +37,12 @@ STDMETHODIMP CWeChatRobot::CSendText(DWORD pid, BSTR wxid, BSTR wxmsg, int *__re } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:艾特的人wxid -* 参数3:文本消息内容 -* 参数4:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:艾特的人wxid + * 参数3:文本消息内容 + * 参数4:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendAtText(DWORD pid, BSTR chatroomid, VARIANT *wxid, BSTR wxmsg, BOOL AutoNickName, int *__result) { *__result = 0; @@ -59,11 +59,11 @@ STDMETHODIMP CWeChatRobot::CSendAtText(DWORD pid, BSTR chatroomid, VARIANT *wxid } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:图片绝对路径 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:图片绝对路径 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendImage(DWORD pid, BSTR wxid, BSTR imagepath, int *__result) { *__result = SendImage(pid, wxid, imagepath); @@ -71,11 +71,11 @@ STDMETHODIMP CWeChatRobot::CSendImage(DWORD pid, BSTR wxid, BSTR imagepath, int } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:文件绝对路径 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:文件绝对路径 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendFile(DWORD pid, BSTR wxid, BSTR filepath, int *__result) { *__result = SendFile(pid, wxid, filepath); @@ -83,13 +83,13 @@ STDMETHODIMP CWeChatRobot::CSendFile(DWORD pid, BSTR wxid, BSTR filepath, int *_ } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:文章标题 -* 参数3:文章摘要 -* 参数4:文章链接 -* 参数5:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:文章标题 + * 参数3:文章摘要 + * 参数4:文章链接 + * 参数5:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendArticle(DWORD pid, BSTR wxid, BSTR title, BSTR abstract, BSTR url, BSTR imgpath, int *__result) { *__result = SendArticle(pid, wxid, title, abstract, url, imgpath); @@ -97,12 +97,12 @@ STDMETHODIMP CWeChatRobot::CSendArticle(DWORD pid, BSTR wxid, BSTR title, BSTR a } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:被分享人wxid -* 参数3:显示的名字 -* 参数4:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:被分享人wxid + * 参数3:显示的名字 + * 参数4:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendCard(DWORD pid, BSTR receiver, BSTR sharedwxid, BSTR nickname, int *__result) { *__result = SendCard(pid, receiver, sharedwxid, nickname); @@ -110,10 +110,10 @@ STDMETHODIMP CWeChatRobot::CSendCard(DWORD pid, BSTR receiver, BSTR sharedwxid, } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -* 返回一个三维数组,python的comtypes包会将其解析为元组 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + * 返回一个三维数组,python的comtypes包会将其解析为元组 + */ STDMETHODIMP CWeChatRobot::CGetFriendList(DWORD pid, VARIANT *__result) { VARIANT vsaValue; @@ -137,10 +137,10 @@ STDMETHODIMP CWeChatRobot::CGetFriendListString(DWORD pid, BSTR *__result) } /* -* 参数0:目标进程pid -* 参数1:要查询的wxid -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:要查询的wxid + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetWxUserInfo(DWORD pid, BSTR wxid, BSTR *__result) { wstring info = GetWxUserInfo(pid, wxid); @@ -149,9 +149,9 @@ STDMETHODIMP CWeChatRobot::CGetWxUserInfo(DWORD pid, BSTR wxid, BSTR *__result) } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetSelfInfo(DWORD pid, BSTR *__result) { wstring info = GetSelfInfo(pid); @@ -160,10 +160,10 @@ STDMETHODIMP CWeChatRobot::CGetSelfInfo(DWORD pid, BSTR *__result) } /* -* 参数0:目标进程pid -* 参数1:查询的wxid -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:查询的wxid + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CCheckFriendStatus(DWORD pid, BSTR wxid, int *__result) { *__result = CheckFriendStatus(pid, (wchar_t *)wxid); @@ -171,8 +171,8 @@ STDMETHODIMP CWeChatRobot::CCheckFriendStatus(DWORD pid, BSTR wxid, int *__resul } /* -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetComWorkPath(BSTR *__result) { wstring path = GetComWorkPath(); @@ -181,9 +181,9 @@ STDMETHODIMP CWeChatRobot::CGetComWorkPath(BSTR *__result) } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CStartReceiveMessage(DWORD pid, int port, int *__result) { *__result = StartReceiveMessage(pid, port); @@ -191,9 +191,9 @@ STDMETHODIMP CWeChatRobot::CStartReceiveMessage(DWORD pid, int port, int *__resu } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CStopReceiveMessage(DWORD pid, int *__result) { *__result = StopReceiveMessage(pid); @@ -201,10 +201,10 @@ STDMETHODIMP CWeChatRobot::CStopReceiveMessage(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:群聊ID -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊ID + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetChatRoomMembers(DWORD pid, BSTR chatroomid, VARIANT *__result) { VARIANT vsaValue; @@ -215,9 +215,9 @@ STDMETHODIMP CWeChatRobot::CGetChatRoomMembers(DWORD pid, BSTR chatroomid, VARIA } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetDbHandles(DWORD pid, VARIANT *__result) { VARIANT vsaValue; @@ -228,11 +228,11 @@ STDMETHODIMP CWeChatRobot::CGetDbHandles(DWORD pid, VARIANT *__result) } /* -* 参数0:目标进程pid -* 参数1:数据库句柄 -* 参数2:要执行的SQL语句 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:数据库句柄 + * 参数2:要执行的SQL语句 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CExecuteSQL(DWORD pid, DWORD DbHandle, BSTR sql, VARIANT *__result) { VARIANT vsaValue; @@ -243,11 +243,11 @@ STDMETHODIMP CWeChatRobot::CExecuteSQL(DWORD pid, DWORD DbHandle, BSTR sql, VARI } /* -* 参数0:目标进程pid -* 参数1:数据库句柄 -* 参数2:备份保存路径 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:数据库句柄 + * 参数2:备份保存路径 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CBackupSQLiteDB(DWORD pid, DWORD DbHandle, BSTR savepath, int *__result) { *__result = BackupSQLiteDB(pid, DbHandle, savepath); @@ -255,11 +255,11 @@ STDMETHODIMP CWeChatRobot::CBackupSQLiteDB(DWORD pid, DWORD DbHandle, BSTR savep } /* -* 参数0:目标进程pid -* 参数1:v3数据 -* 参数2:v4数据 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:v3数据 + * 参数2:v4数据 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CVerifyFriendApply(DWORD pid, BSTR v3, BSTR v4, int *__result) { *__result = VerifyFriendApply(pid, v3, v4); @@ -267,11 +267,11 @@ STDMETHODIMP CWeChatRobot::CVerifyFriendApply(DWORD pid, BSTR v3, BSTR v4, int * } /* -* 参数0:目标进程pid -* 参数1:wxid -* 参数2:附加信息 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:wxid + * 参数2:附加信息 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CAddFriendByWxid(DWORD pid, BSTR wxid, BSTR message, int *__result) { *__result = AddFriendByWxid(pid, wxid, message); @@ -279,12 +279,12 @@ STDMETHODIMP CWeChatRobot::CAddFriendByWxid(DWORD pid, BSTR wxid, BSTR message, } /* -* 参数0:目标进程pid -* 参数1:v3数据 -* 参数2:附加信息 -* 参数3:添加方式 -* 参数4:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:v3数据 + * 参数2:附加信息 + * 参数3:添加方式 + * 参数4:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CAddFriendByV3(DWORD pid, BSTR v3, BSTR message, int AddType, int *__result) { *__result = AddFriendByV3(pid, v3, message, AddType); @@ -292,9 +292,9 @@ STDMETHODIMP CWeChatRobot::CAddFriendByV3(DWORD pid, BSTR v3, BSTR message, int } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetWeChatVer(BSTR *__result) { wstring path = GetWeChatVerStr(); @@ -303,8 +303,8 @@ STDMETHODIMP CWeChatRobot::CGetWeChatVer(BSTR *__result) } /* -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CStartWeChat(int *__result) { *__result = StartWeChat(); @@ -312,10 +312,10 @@ STDMETHODIMP CWeChatRobot::CStartWeChat(int *__result) } /* -* 参数0:目标进程pid -* 参数1:搜索关键字 -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:搜索关键字 + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSearchContactByNet(DWORD pid, BSTR keyword, VARIANT *__result) { VARIANT vsaValue; @@ -326,10 +326,10 @@ STDMETHODIMP CWeChatRobot::CSearchContactByNet(DWORD pid, BSTR keyword, VARIANT } /* -* 参数0:目标进程pid -* 参数1:公众号id -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:公众号id + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CAddBrandContact(DWORD pid, BSTR PublicId, int *__result) { *__result = AddBrandContact(pid, PublicId); @@ -337,10 +337,10 @@ STDMETHODIMP CWeChatRobot::CAddBrandContact(DWORD pid, BSTR PublicId, int *__res } /* -* 参数0:目标进程pid -* 参数1:保存路径 -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:保存路径 + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CHookVoiceMsg(DWORD pid, BSTR savepath, int *__result) { *__result = HookVoiceMsg(pid, savepath); @@ -348,9 +348,9 @@ STDMETHODIMP CWeChatRobot::CHookVoiceMsg(DWORD pid, BSTR savepath, int *__result } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CUnHookVoiceMsg(DWORD pid, int *__result) { UnHookVoiceMsg(pid); @@ -359,10 +359,10 @@ STDMETHODIMP CWeChatRobot::CUnHookVoiceMsg(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:保存路径 -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:保存路径 + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CHookImageMsg(DWORD pid, BSTR savepath, int *__result) { *__result = HookImageMsg(pid, savepath); @@ -370,9 +370,9 @@ STDMETHODIMP CWeChatRobot::CHookImageMsg(DWORD pid, BSTR savepath, int *__result } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CUnHookImageMsg(DWORD pid, int *__result) { UnHookImageMsg(pid); @@ -381,10 +381,10 @@ STDMETHODIMP CWeChatRobot::CUnHookImageMsg(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:版本号 -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:版本号 + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CChangeWeChatVer(DWORD pid, BSTR verStr, int *__result) { *__result = ChangeWeChatVer(pid, verStr); @@ -392,11 +392,11 @@ STDMETHODIMP CWeChatRobot::CChangeWeChatVer(DWORD pid, BSTR verStr, int *__resul } /* -* 参数0:目标进程pid -* 参数1:接收人wxid -* 参数2:小程序id -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:接收人wxid + * 参数2:小程序id + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSendAppMsg(DWORD pid, BSTR wxid, BSTR appid, int *__result) { *__result = SendAppMsg(pid, wxid, appid); @@ -404,10 +404,10 @@ STDMETHODIMP CWeChatRobot::CSendAppMsg(DWORD pid, BSTR wxid, BSTR appid, int *__ } /* -* 参数0:目标进程pid -* 参数1:要删除的人wxid -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:要删除的人wxid + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CDeleteUser(DWORD pid, BSTR wxid, int *__result) { *__result = DeleteUser(pid, wxid); @@ -415,9 +415,9 @@ STDMETHODIMP CWeChatRobot::CDeleteUser(DWORD pid, BSTR wxid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CIsWxLogin(DWORD pid, int *__result) { *__result = isWxLogin(pid); @@ -425,11 +425,11 @@ STDMETHODIMP CWeChatRobot::CIsWxLogin(DWORD pid, int *__result) } /* -* 参数0:目标进程pid -* 参数1:wxid或群聊id -* 参数2:备注内容 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:wxid或群聊id + * 参数2:备注内容 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CEditRemark(DWORD pid, BSTR wxid, BSTR remark, int *__result) { *__result = EditRemark(pid, wxid, remark); @@ -437,11 +437,11 @@ STDMETHODIMP CWeChatRobot::CEditRemark(DWORD pid, BSTR wxid, BSTR remark, int *_ } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:群聊名称 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:群聊名称 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSetChatRoomName(DWORD pid, BSTR chatroomid, BSTR name, int *__result) { *__result = SetChatRoomName(pid, chatroomid, name); @@ -449,11 +449,11 @@ STDMETHODIMP CWeChatRobot::CSetChatRoomName(DWORD pid, BSTR chatroomid, BSTR nam } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:公告内容 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:公告内容 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSetChatRoomAnnouncement(DWORD pid, BSTR chatroomid, BSTR announcement, int *__result) { *__result = SetChatRoomAnnouncement(pid, chatroomid, announcement); @@ -461,11 +461,11 @@ STDMETHODIMP CWeChatRobot::CSetChatRoomAnnouncement(DWORD pid, BSTR chatroomid, } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:个人昵称 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:个人昵称 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CSetChatRoomSelfNickname(DWORD pid, BSTR chatroomid, BSTR nickname, int *__result) { *__result = SetChatRoomSelfNickname(pid, chatroomid, nickname); @@ -473,11 +473,11 @@ STDMETHODIMP CWeChatRobot::CSetChatRoomSelfNickname(DWORD pid, BSTR chatroomid, } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:群成员wxid -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:群成员wxid + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetChatRoomMemberNickname(DWORD pid, BSTR chatroomid, BSTR wxid, BSTR *__result) { wstring nickname = GetChatRoomMemberNickname(pid, chatroomid, wxid); @@ -486,11 +486,11 @@ STDMETHODIMP CWeChatRobot::CGetChatRoomMemberNickname(DWORD pid, BSTR chatroomid } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:wxid列表 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:wxid列表 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CDelChatRoomMember(DWORD pid, BSTR chatroomid, VARIANT *wxids, int *__result) { if (wxids->vt == VT_BSTR) @@ -506,11 +506,11 @@ STDMETHODIMP CWeChatRobot::CDelChatRoomMember(DWORD pid, BSTR chatroomid, VARIAN } /* -* 参数0:目标进程pid -* 参数1:群聊id -* 参数2:wxid列表 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:群聊id + * 参数2:wxid列表 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CAddChatRoomMember(DWORD pid, BSTR chatroomid, VARIANT *wxids, int *__result) { if (wxids->vt == VT_BSTR) @@ -526,10 +526,10 @@ STDMETHODIMP CWeChatRobot::CAddChatRoomMember(DWORD pid, BSTR chatroomid, VARIAN } /* -* 参数0:目标进程pid -* 参数1:要打开的网页url -* 参数2:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:要打开的网页url + * 参数2:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::COpenBrowser(DWORD pid, BSTR url, int *__result) { *__result = OpenBrowser(pid, url); @@ -537,11 +537,11 @@ STDMETHODIMP CWeChatRobot::COpenBrowser(DWORD pid, BSTR url, int *__result) } /* -* 参数0:目标进程pid -* 参数1:公众号ID -* 参数2:推送消息的偏移 -* 参数3:预返回的值,调用时无需提供 -*/ + * 参数0:目标进程pid + * 参数1:公众号ID + * 参数2:推送消息的偏移 + * 参数3:预返回的值,调用时无需提供 + */ STDMETHODIMP CWeChatRobot::CGetHistoryPublicMsg(DWORD pid, BSTR PublicId, BSTR Offset, VARIANT *__result) { HRESULT hr = S_OK; @@ -557,3 +557,9 @@ STDMETHODIMP CWeChatRobot::CGetHistoryPublicMsg(DWORD pid, BSTR PublicId, BSTR O *__result = vsaValue; return S_OK; } + +STDMETHODIMP CWeChatRobot::CForwardMessage(DWORD pid, BSTR wxid, int localId, int *__result) +{ + *__result = ForwardMessage(pid, wxid, localId); + return S_OK; +} diff --git a/CWeChatRobot/WeChatRobot.h b/CWeChatRobot/WeChatRobot.h index e617cdb441497d0c6f1b35e2e1cd062a24b1711e..8fb612e68ae6284c897cfea587627e9b8ca982c5 100644 --- a/CWeChatRobot/WeChatRobot.h +++ b/CWeChatRobot/WeChatRobot.h @@ -85,6 +85,7 @@ public: STDMETHODIMP CAddChatRoomMember(DWORD pid, BSTR chatroomid, VARIANT *wxids, int *__result); STDMETHODIMP COpenBrowser(DWORD pid, BSTR url, int *__result); STDMETHODIMP CGetHistoryPublicMsg(DWORD pid, BSTR PublicId, BSTR Offset, VARIANT *__result); + STDMETHODIMP CForwardMessage(DWORD pid, BSTR wxid, int localId, int *__result); }; OBJECT_ENTRY_AUTO(__uuidof(WeChatRobot), CWeChatRobot) diff --git a/CWeChatRobot/WeChatRobotCOM.idl b/CWeChatRobot/WeChatRobotCOM.idl index 998ca14edb91893c1def669720a611724a07541b..8e7d990a358d28f583b0e1ee6584a0f687322b31 100644 --- a/CWeChatRobot/WeChatRobotCOM.idl +++ b/CWeChatRobot/WeChatRobotCOM.idl @@ -59,7 +59,8 @@ interface IWeChatRobot : IDispatch [id(44), helpstring("删除群成员")] HRESULT CDelChatRoomMember([in] DWORD pid, [in] BSTR chatroomid, [in] VARIANT* wxids, [out, retval] int* __result); [id(45), helpstring("添加群成员")] HRESULT CAddChatRoomMember([in] DWORD pid, [in] BSTR chatroomid, [in] VARIANT* wxids, [out, retval] int* __result); [id(46), helpstring("打开微信内置浏览器")] HRESULT COpenBrowser([in] DWORD pid, [in] BSTR url, [ out, retval ] int *__result); - [id(47), helpstring("获取公众号历史消息")] HRESULT CGetHistoryPublicMsg([in] DWORD pid, [in] BSTR PublicId, [in] BSTR Offset, [ out, retval ] VARIANT * __result); + [id(47), helpstring("获取公众号历史消息")] HRESULT CGetHistoryPublicMsg([in] DWORD pid, [in] BSTR PublicId, [in] BSTR Offset, [out, retval] VARIANT * __result); + [id(48), helpstring("转发消息") ] HRESULT CForwardMessage([in] DWORD pid, [in] BSTR wxid, [in] int localId, [out, retval] int * __result); }; [ object, diff --git a/CWeChatRobot/WeChatRobotCOM.vcxproj b/CWeChatRobot/WeChatRobotCOM.vcxproj index 1fc3f1eb71b651edda8904564f9352c7beea78ba..956eba37a4c1ca63d8a6a517af639b450860139f 100644 --- a/CWeChatRobot/WeChatRobotCOM.vcxproj +++ b/CWeChatRobot/WeChatRobotCOM.vcxproj @@ -229,6 +229,7 @@ + @@ -276,6 +277,7 @@ + diff --git a/CWeChatRobot/WeChatRobotCOM.vcxproj.filters b/CWeChatRobot/WeChatRobotCOM.vcxproj.filters index 2d77a6d4bf33275d3af139b1d9ae8a6a9dab25d0..58e690a6d8ba88a0c65c41bc4ad71e37e0c08ed9 100644 --- a/CWeChatRobot/WeChatRobotCOM.vcxproj.filters +++ b/CWeChatRobot/WeChatRobotCOM.vcxproj.filters @@ -125,6 +125,9 @@ {e54ac438-bc4e-46cf-9450-502e35daf385} + + {f44839a7-3cf0-415f-886e-22a8635c3dbd} + @@ -256,6 +259,9 @@ 浏览器相关\获取公众号历史消息 + + 发送消息\转发消息 + @@ -387,6 +393,9 @@ 浏览器相关\获取公众号历史消息 + + 发送消息\转发消息 + diff --git a/CWeChatRobot/WeChatRobotCOM_i.h b/CWeChatRobot/WeChatRobotCOM_i.h index e549a25cf1b921f1a54d8ad362f015ffdd58b43a..08aeed4255b020e812422a4cd0e70f9f9786c7a3 100644 --- a/CWeChatRobot/WeChatRobotCOM_i.h +++ b/CWeChatRobot/WeChatRobotCOM_i.h @@ -345,6 +345,12 @@ EXTERN_C const IID IID_IWeChatRobot; /* [in] */ BSTR Offset, /* [retval][out] */ VARIANT *__result) = 0; + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CForwardMessage( + /* [in] */ DWORD pid, + /* [in] */ BSTR wxid, + /* [in] */ int localId, + /* [retval][out] */ int *__result) = 0; + }; @@ -678,6 +684,13 @@ EXTERN_C const IID IID_IWeChatRobot; /* [in] */ BSTR Offset, /* [retval][out] */ VARIANT *__result); + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CForwardMessage )( + IWeChatRobot * This, + /* [in] */ DWORD pid, + /* [in] */ BSTR wxid, + /* [in] */ int localId, + /* [retval][out] */ int *__result); + END_INTERFACE } IWeChatRobotVtbl; @@ -846,6 +859,9 @@ EXTERN_C const IID IID_IWeChatRobot; #define IWeChatRobot_CGetHistoryPublicMsg(This,pid,PublicId,Offset,__result) \ ( (This)->lpVtbl -> CGetHistoryPublicMsg(This,pid,PublicId,Offset,__result) ) +#define IWeChatRobot_CForwardMessage(This,pid,wxid,localId,__result) \ + ( (This)->lpVtbl -> CForwardMessage(This,pid,wxid,localId,__result) ) + #endif /* COBJMACROS */ diff --git a/CWeChatRobot/WeChatRobotCOM_p.c b/CWeChatRobot/WeChatRobotCOM_p.c index 3dadfec4734ee45c3ffa13938e414c97c7f22bf9..8ceb1bcaead58e346a2c9700a950717745eb8330 100644 --- a/CWeChatRobot/WeChatRobotCOM_p.c +++ b/CWeChatRobot/WeChatRobotCOM_p.c @@ -49,7 +49,7 @@ #include "WeChatRobotCOM_i.h" #define TYPE_FORMAT_STRING_SIZE 1239 -#define PROC_FORMAT_STRING_SIZE 2287 +#define PROC_FORMAT_STRING_SIZE 2341 #define EXPR_FORMAT_STRING_SIZE 1 #define TRANSMIT_AS_TABLE_SIZE 0 #define WIRE_MARSHAL_TABLE_SIZE 2 @@ -2106,17 +2106,17 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor /* 2176 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Procedure CPostMessage */ + /* Procedure CForwardMessage */ /* 2178 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ /* 2180 */ NdrFcLong( 0x0 ), /* 0 */ -/* 2184 */ NdrFcShort( 0x7 ), /* 7 */ -/* 2186 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ -/* 2188 */ NdrFcShort( 0x20 ), /* 32 */ +/* 2184 */ NdrFcShort( 0x33 ), /* 51 */ +/* 2186 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 2188 */ NdrFcShort( 0x10 ), /* 16 */ /* 2190 */ NdrFcShort( 0x24 ), /* 36 */ /* 2192 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ - 0x6, /* 6 */ + 0x5, /* 5 */ /* 2194 */ 0x8, /* 8 */ 0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */ /* 2196 */ NdrFcShort( 0x0 ), /* 0 */ @@ -2130,83 +2130,134 @@ static const WeChatRobotCOM_MIDL_PROC_FORMAT_STRING WeChatRobotCOM__MIDL_ProcFor /* 2206 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ - /* Parameter msgtype */ + /* Parameter wxid */ -/* 2208 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2208 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ /* 2210 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 2212 */ 0x8, /* FC_LONG */ - 0x0, /* 0 */ +/* 2212 */ NdrFcShort( 0x2a ), /* Type Offset=42 */ - /* Parameter msgid */ + /* Parameter localId */ /* 2214 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ /* 2216 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 2218 */ 0xb, /* FC_HYPER */ +/* 2218 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __result */ + +/* 2220 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2222 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 2224 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2226 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2228 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2230 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure CPostMessage */ + +/* 2232 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2234 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2238 */ NdrFcShort( 0x7 ), /* 7 */ +/* 2240 */ NdrFcShort( 0x20 ), /* x86 Stack size/offset = 32 */ +/* 2242 */ NdrFcShort( 0x20 ), /* 32 */ +/* 2244 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2246 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x6, /* 6 */ +/* 2248 */ 0x8, /* 8 */ + 0x45, /* Ext Flags: new corr desc, srv corr check, has range on conformance */ +/* 2250 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2252 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2254 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter pid */ + +/* 2256 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2258 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 2260 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter msgtype */ + +/* 2262 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2264 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 2266 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter msgid */ + +/* 2268 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2270 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 2272 */ 0xb, /* FC_HYPER */ 0x0, /* 0 */ /* Parameter msg */ -/* 2220 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ -/* 2222 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 2224 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */ +/* 2274 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 2276 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2278 */ NdrFcShort( 0x4cc ), /* Type Offset=1228 */ /* Parameter __result */ -/* 2226 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ -/* 2228 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ -/* 2230 */ 0x8, /* FC_LONG */ +/* 2280 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2282 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */ +/* 2284 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Return value */ -/* 2232 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 2234 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ -/* 2236 */ 0x8, /* FC_LONG */ +/* 2286 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2288 */ NdrFcShort( 0x1c ), /* x86 Stack size/offset = 28 */ +/* 2290 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Procedure CRegisterWxPidWithCookie */ -/* 2238 */ 0x33, /* FC_AUTO_HANDLE */ +/* 2292 */ 0x33, /* FC_AUTO_HANDLE */ 0x6c, /* Old Flags: object, Oi2 */ -/* 2240 */ NdrFcLong( 0x0 ), /* 0 */ -/* 2244 */ NdrFcShort( 0x8 ), /* 8 */ -/* 2246 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ -/* 2248 */ NdrFcShort( 0x10 ), /* 16 */ -/* 2250 */ NdrFcShort( 0x24 ), /* 36 */ -/* 2252 */ 0x44, /* Oi2 Flags: has return, has ext, */ +/* 2294 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2298 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2300 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 2302 */ NdrFcShort( 0x10 ), /* 16 */ +/* 2304 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2306 */ 0x44, /* Oi2 Flags: has return, has ext, */ 0x4, /* 4 */ -/* 2254 */ 0x8, /* 8 */ +/* 2308 */ 0x8, /* 8 */ 0x41, /* Ext Flags: new corr desc, has range on conformance */ -/* 2256 */ NdrFcShort( 0x0 ), /* 0 */ -/* 2258 */ NdrFcShort( 0x0 ), /* 0 */ -/* 2260 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2310 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2312 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2314 */ NdrFcShort( 0x0 ), /* 0 */ /* Parameter pid */ -/* 2262 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 2264 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ -/* 2266 */ 0x8, /* FC_LONG */ +/* 2316 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2318 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 2320 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter cookie */ -/* 2268 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ -/* 2270 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ -/* 2272 */ 0x8, /* FC_LONG */ +/* 2322 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2324 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 2326 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Parameter __result */ -/* 2274 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ -/* 2276 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ -/* 2278 */ 0x8, /* FC_LONG */ +/* 2328 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2330 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 2332 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ /* Return value */ -/* 2280 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ -/* 2282 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ -/* 2284 */ 0x8, /* FC_LONG */ +/* 2334 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2336 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 2338 */ 0x8, /* FC_LONG */ 0x0, /* 0 */ 0x0 @@ -3097,7 +3148,8 @@ static const unsigned short IWeChatRobot_FormatStringOffsetTable[] = 1968, 2022, 2076, - 2124 + 2124, + 2178 }; static const MIDL_STUBLESS_PROXY_INFO IWeChatRobot_ProxyInfo = @@ -3121,7 +3173,7 @@ static const MIDL_SERVER_INFO IWeChatRobot_ServerInfo = 0, 0, 0}; -CINTERFACE_PROXY_VTABLE(51) _IWeChatRobotProxyVtbl = +CINTERFACE_PROXY_VTABLE(52) _IWeChatRobotProxyVtbl = { &IWeChatRobot_ProxyInfo, &IID_IWeChatRobot, @@ -3175,7 +3227,8 @@ CINTERFACE_PROXY_VTABLE(51) _IWeChatRobotProxyVtbl = (void *) (INT_PTR) -1 /* IWeChatRobot::CDelChatRoomMember */ , (void *) (INT_PTR) -1 /* IWeChatRobot::CAddChatRoomMember */ , (void *) (INT_PTR) -1 /* IWeChatRobot::COpenBrowser */ , - (void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */ + (void *) (INT_PTR) -1 /* IWeChatRobot::CGetHistoryPublicMsg */ , + (void *) (INT_PTR) -1 /* IWeChatRobot::CForwardMessage */ }; @@ -3228,6 +3281,7 @@ static const PRPC_STUB_FUNCTION IWeChatRobot_table[] = NdrStubCall2, NdrStubCall2, NdrStubCall2, + NdrStubCall2, NdrStubCall2 }; @@ -3235,7 +3289,7 @@ CInterfaceStubVtbl _IWeChatRobotStubVtbl = { &IID_IWeChatRobot, &IWeChatRobot_ServerInfo, - 51, + 52, &IWeChatRobot_table[-3], CStdStubBuffer_DELEGATING_METHODS }; @@ -3251,8 +3305,8 @@ static const unsigned short IRobotEvent_FormatStringOffsetTable[] = (unsigned short) -1, (unsigned short) -1, (unsigned short) -1, - 2178, - 2238 + 2232, + 2292 }; static const MIDL_STUBLESS_PROXY_INFO IRobotEvent_ProxyInfo = diff --git a/CWeChatRobot/_IRobotEventEvents_CP.h b/CWeChatRobot/_IRobotEventEvents_CP.h index 2fc8e36824b02b4cb42c09af0f1d1c8549efd53e..bf7cbf442d93dd897afd205468c9369aa9f80d7b 100644 --- a/CWeChatRobot/_IRobotEventEvents_CP.h +++ b/CWeChatRobot/_IRobotEventEvents_CP.h @@ -17,7 +17,7 @@ public: { HRESULT hr = S_OK; static ExpireSet es(2000); - if (!es.CheckIfDuplicatedAndAdd(msgid)) + if (msgid && !es.CheckIfDuplicatedAndAdd(msgid)) { return hr; } diff --git a/CWeChatRobot/robotdata.h b/CWeChatRobot/robotdata.h index f1183eba3ca83fc871678389d57b597fef26d818..5c22665c9c9f6d4afa93769aff0a9a682b21e981 100644 --- a/CWeChatRobot/robotdata.h +++ b/CWeChatRobot/robotdata.h @@ -29,6 +29,7 @@ #include "AddChatRoomMember.h" #include "OpenBrowser.h" #include "GetHistoryPublicMsg.h" +#include "ForwardMessage.h" #define DLLNAME L"DWeChatRobot.dll" @@ -39,6 +40,7 @@ #define SendCardRemote "SendCardRemote" #define SendAtTextRemote "SendAtTextRemote" #define SendAppMsgRemote "SendAppMsgRemote" +#define ForwardMessageRemote "ForwardMessageRemote" #define GetFriendListInit "GetFriendListInit" #define GetFriendListRemote "GetFriendListRemote" diff --git a/DWeChatRobot/DWeChatRobot.vcxproj b/DWeChatRobot/DWeChatRobot.vcxproj index 83b0d11723f7e5753303f94b0bf260a69290dba9..bdee442e0023d4f6b9a7f6af8942dad751e3bb5f 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj +++ b/DWeChatRobot/DWeChatRobot.vcxproj @@ -317,6 +317,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http + @@ -361,6 +362,7 @@ xcopy /y /d "$(OutDir)..\..\Python\http\wxDriver.py" "$(SolutionDir)build\http + diff --git a/DWeChatRobot/DWeChatRobot.vcxproj.filters b/DWeChatRobot/DWeChatRobot.vcxproj.filters index 3549ba6e074d354d533172fb3883f23968ef8c1b..02e75ed46e155f5f8b6b2b5bc36cc246b18ba932 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj.filters +++ b/DWeChatRobot/DWeChatRobot.vcxproj.filters @@ -124,6 +124,9 @@ {05d4d999-8961-4c1a-82fb-a36e3a4965f8} + + {da7b0dbb-2d48-473f-9bb9-6d36ec5b02d3} + @@ -240,6 +243,9 @@ 浏览器相关\获取公众号历史信息 + + 发送消息\转发消息 + @@ -362,5 +368,8 @@ 浏览器相关\获取公众号历史信息 + + 发送消息\转发消息 + diff --git a/DWeChatRobot/ForwardMessage.cpp b/DWeChatRobot/ForwardMessage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e3d7340d609cc5bf0c3b69658eccc580b1800d4 --- /dev/null +++ b/DWeChatRobot/ForwardMessage.cpp @@ -0,0 +1,47 @@ +#include "pch.h" + +#define ForwardMessageCall1Offset 0x771980 +#define ForwardMessageCall2Offset 0x521760 + +#ifndef USE_SOCKET +struct ForwardMessageStruct +{ + wchar_t *wxid; + int localId; +}; + +BOOL ForwardMessageRemote(LPVOID lpParameter) +{ + ForwardMessageStruct *fms = (ForwardMessageStruct *)lpParameter; + return ForwardMessage(fms->wxid, fms->localId); +} +#endif + +BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId) +{ + DWORD WeChatWinBase = GetWeChatWinBase(); + DWORD ForwardMessageCall1 = WeChatWinBase + ForwardMessageCall1Offset; + DWORD ForwardMessageCall2 = WeChatWinBase + ForwardMessageCall2Offset; + WxString p_wxid(wxid); + int isSuccess = 0; + __asm { + pushad; + pushfd; + mov eax, 0x5000100; + push eax; + mov ecx, dword ptr ds:[localId]; + push ecx; + lea edi, p_wxid; + sub esp, 0x14; + mov ecx, esp; + push edi; + call ForwardMessageCall1; + call ForwardMessageCall2; + movzx eax,al; + mov isSuccess,eax; + add esp, 0x1C; + popfd; + popad; + } + return isSuccess == 0x1; +} diff --git a/DWeChatRobot/ForwardMessage.h b/DWeChatRobot/ForwardMessage.h new file mode 100644 index 0000000000000000000000000000000000000000..c533bb7d337dbea2415c344bd7e60839de117d63 --- /dev/null +++ b/DWeChatRobot/ForwardMessage.h @@ -0,0 +1,7 @@ +#pragma once +#include +BOOL __stdcall ForwardMessage(wchar_t *wxid, int localId); + +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) BOOL ForwardMessageRemote(LPVOID lpParameter); +#endif diff --git a/DWeChatRobot/ReceiveMessage.cpp b/DWeChatRobot/ReceiveMessage.cpp index 28b302c3c793d77e4fa8df11bbc9af72cc079881..90cab62421c73e8d1ace04401335124c5ee34ca6 100644 --- a/DWeChatRobot/ReceiveMessage.cpp +++ b/DWeChatRobot/ReceiveMessage.cpp @@ -13,15 +13,20 @@ using namespace std; #define CLTIP "127.0.0.1" // ϢHOOKַƫ -#define ReceiveMessageHookOffset 0x78BF0F4C - 0x786A0000 +#define ReceiveMessageHookOffset 0x5D39C359 - 0x5D1F0000 // ϢHOOKCALLƫ -#define ReceiveMessageNextCallOffset 0x79136350 - 0x786A0000 +#define ReceiveMessageNextCallOffset 0x5D5F7F00 - 0x5D1F0000 // ϢHOOKַƫ #define SendMessageHookOffset 0x78B88E42 - 0x786A0000 // ϢHOOKCALLƫ #define SendMessageNextCallOffset 0x78AA8170 - 0x786A0000 +// ϢHOOKַƫ +#define RevokeMessageHookOffset 0x5D6D8A4C - 0x5D1F0000 +// ϢHOOKCALLƫ +#define RevokeMessageNextCallOffset 0x5D6D3430 - 0x5D1F0000 + #define READ_WSTRING(addr, offset) wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4)) static int SRVPORT = 0; @@ -29,8 +34,9 @@ static int SRVPORT = 0; // ǷϢHOOK־ BOOL ReceiveMessageHooked = false; // HOOKǰֽ룬ڻָ -char OldReceiveMessageAsmCode[5] = {0}; -char OldSendMessageAsmCode[5] = {0}; +static char OldReceiveMessageAsmCode[5] = {0}; +static char OldSendMessageAsmCode[5] = {0}; +static char OldRevokeMessageAsmCode[5] = {0}; static DWORD WeChatWinBase = GetWeChatWinBase(); // ϢHOOKַ static DWORD ReceiveMessageHookAddress = WeChatWinBase + ReceiveMessageHookOffset; @@ -44,6 +50,12 @@ static DWORD SendMessageHookAddress = WeChatWinBase + SendMessageHookOffset; static DWORD SendMessageNextCall = WeChatWinBase + SendMessageNextCallOffset; // HOOKתַ static DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5; +// ϢHOOKַ +static DWORD RevokeMessageHookAddress = WeChatWinBase + RevokeMessageHookOffset; +// ϢHOOKCALLַ +static DWORD RevokeMessageNextCall = WeChatWinBase + RevokeMessageNextCallOffset; +// HOOKתַ +static DWORD RevokeMessageJmpBackAddress = RevokeMessageHookAddress + 0x5; struct SocketMessageStruct { @@ -120,6 +132,17 @@ void SendSocketMessageInThread(SocketMessageStruct *param) return; unique_ptr sms(param); string jstr(param->buffer, param->length); +#ifdef USE_COM + // ͨӵ㣬Ϣ㲥ͻˣ㲥̷߳ɣͻ˲ſԵȴͼƬ + VARIANT vsaValue = (_variant_t)utf8_to_unicode(jstr.c_str()).c_str(); + json jMsg = json::parse(param->buffer, param->buffer + param->length, nullptr, false); + if (jMsg.is_discarded() != true) + { + DWORD type = jMsg["type"].get(); + ULONG64 msgid = (type != 10000) ? jMsg["msgid"].get() : 0; + PostComMessage(jMsg["pid"].get(), WX_MESSAGE, msgid, &vsaValue); + } +#endif SendSocketMessage(jstr.c_str(), jstr.size()); } @@ -131,21 +154,25 @@ static void dealMessage(DWORD messageAddr) jMsg["type"] = *(DWORD *)(messageAddr + 0x38); jMsg["isSendMsg"] = *(BOOL *)(messageAddr + 0x3C); jMsg["msgid"] = msgid; + jMsg["localId"] = *(unsigned int *)(messageAddr + 0x20); jMsg["sender"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x48).c_str()); int length = *(DWORD *)(messageAddr + 0x170 + 0x4); jMsg["wxid"] = length == 0 ? jMsg["sender"].get() : unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x170).c_str()); jMsg["message"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x70).c_str()); - jMsg["filepath"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1AC).c_str()); - string extrabuf = base64_encode((BYTE *)(*(DWORD *)(messageAddr + 0x8C)), *(DWORD *)(messageAddr + 0x8C + 0x4)); - jMsg["extrainfo"] = extrabuf; + if (jMsg["type"].get() != 10000) + { + jMsg["filepath"] = unicode_to_utf8((wchar_t *)READ_WSTRING(messageAddr, 0x1AC).c_str()); + string extrabuf = base64_encode((BYTE *)(*(DWORD *)(messageAddr + 0x8C)), *(DWORD *)(messageAddr + 0x8C + 0x4)); + jMsg["extrainfo"] = extrabuf; + } + else + { + // Ϊ˽ṩѳϢԭϢ + jMsg["extrainfo"] = ""; + } jMsg["time"] = unicode_to_utf8((wchar_t *)GetTimeW(*(DWORD *)(messageAddr + 0x44)).c_str()); jMsg["self"] = unicode_to_utf8((wchar_t *)GetSelfWxid().c_str()); string jstr = jMsg.dump() + '\n'; -#ifdef USE_COM - // ͨӵ㣬Ϣ㲥ͻ - VARIANT vsaValue = (_variant_t)utf8_to_unicode(jstr.c_str()).c_str(); - PostComMessage(jMsg["pid"].get(), WX_MESSAGE, msgid, &vsaValue); -#endif // Ϊ֤̰߳ȫҪֶڴ SocketMessageStruct *sms = new SocketMessageStruct; sms->buffer = new char[jstr.size() + 1]; @@ -163,15 +190,14 @@ static void dealMessage(DWORD messageAddr) * messageAddrϢĻַ * returnvoid */ -VOID ReceiveMessage(DWORD messagesAddr) -{ - // ˴Ƿ͵ĻǽյϢ - DWORD *messages = (DWORD *)messagesAddr; - for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298) - { - dealMessage(messageAddr); - } -} +// VOID ReceiveMessage(DWORD messagesAddr) +//{ +// DWORD *messages = (DWORD *)messagesAddr; +// for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298) +// { +// dealMessage(messageAddr); +// } +// } /* * HOOKľʵ֣յϢô @@ -182,7 +208,7 @@ _declspec(naked) void dealReceiveMessage() pushad; pushfd; push edi; - call ReceiveMessage; + call dealMessage; add esp, 0x4; popfd; popad; @@ -209,6 +235,24 @@ _declspec(naked) void dealSendMessage() } } +/* + * HOOKľʵ֣յϢô + */ +_declspec(naked) void dealRevokeMessage() +{ + __asm { + pushad; + pushfd; + push edi; + call dealMessage; + add esp, 0x4; + popfd; + popad; + call RevokeMessageNextCall; + jmp RevokeMessageJmpBackAddress; + } +} + /* * ʼϢHOOK * returnvoid @@ -225,8 +269,12 @@ VOID HookReceiveMessage(int port) SendMessageHookAddress = WeChatWinBase + SendMessageHookOffset; SendMessageNextCall = WeChatWinBase + SendMessageNextCallOffset; SendMessageJmpBackAddress = SendMessageHookAddress + 0x5; + RevokeMessageHookAddress = WeChatWinBase + RevokeMessageHookOffset; + RevokeMessageNextCall = WeChatWinBase + RevokeMessageNextCallOffset; + RevokeMessageJmpBackAddress = RevokeMessageHookAddress + 0x5; HookAnyAddress(ReceiveMessageHookAddress, (LPVOID)dealReceiveMessage, OldReceiveMessageAsmCode); HookAnyAddress(SendMessageHookAddress, (LPVOID)dealSendMessage, OldSendMessageAsmCode); + HookAnyAddress(RevokeMessageHookAddress, (LPVOID)dealRevokeMessage, OldRevokeMessageAsmCode); ReceiveMessageHooked = TRUE; } @@ -241,5 +289,6 @@ VOID UnHookReceiveMessage() return; UnHookAnyAddress(ReceiveMessageHookAddress, OldReceiveMessageAsmCode); UnHookAnyAddress(SendMessageHookAddress, OldSendMessageAsmCode); + UnHookAnyAddress(RevokeMessageHookAddress, OldRevokeMessageAsmCode); ReceiveMessageHooked = FALSE; } diff --git a/DWeChatRobot/http_overload.hpp b/DWeChatRobot/http_overload.hpp index 79aef15af1b9d6b403ec9dd02ce72ed4e0387baa..d25ee8fd41c1dd21b6abc5318d68569a7592f178 100644 --- a/DWeChatRobot/http_overload.hpp +++ b/DWeChatRobot/http_overload.hpp @@ -133,4 +133,9 @@ BOOL __stdcall OpenBrowser(wstring url) { return OpenBrowser(WS2LW(url)); } + +BOOL __stdcall ForwardMessage(wstring wxid, int localId) +{ + return ForwardMessage(WS2LW(wxid), localId); +} #endif diff --git a/DWeChatRobot/wxapi.h b/DWeChatRobot/wxapi.h index 38e00f914c7bbaf806f7af622864c01d9c29be79..23918bb9b4cbdb95e9df1722ee5ab0c5b5b0a9e5 100644 --- a/DWeChatRobot/wxapi.h +++ b/DWeChatRobot/wxapi.h @@ -30,6 +30,7 @@ #include "GetChatRoomMemberNickname.h" #include "OpenBrowser.h" #include "GetHistoryPublicMsg.h" +#include "ForwardMessage.h" using namespace std; #pragma comment(lib, "version.lib") diff --git a/DWeChatRobot/wxsocket.cpp b/DWeChatRobot/wxsocket.cpp index 73070ed737e150749b3e067a99af10919ff7f64d..3de21060288a29e8c79be24742e716b49202e351 100644 --- a/DWeChatRobot/wxsocket.cpp +++ b/DWeChatRobot/wxsocket.cpp @@ -531,6 +531,15 @@ void request_event(mg_http_message *hm, string &ret) ret = ret_data.dump(); break; } + case WECHAT_MSG_FORWARD_MESSAGE: + { + wstring wxid = get_http_param_str(hm, jData, "wxid", method); + int localId = get_http_param_int(hm, jData, "localId", method); + BOOL status = ForwardMessage(wxid, localId); + json ret_data = {{"msg", status}, {"result", "OK"}}; + ret = ret_data.dump(); + break; + } default: // char* wxid = mg_json_get_str(hm->body, "$.wxid"); break; diff --git a/DWeChatRobot/wxsocketapi.h b/DWeChatRobot/wxsocketapi.h index 25c3c863bb769e8cfa994c15ab37d38b2abe512b..a8737cb5d94dcb8876d2e7012fb42ea9bd2baa88 100644 --- a/DWeChatRobot/wxsocketapi.h +++ b/DWeChatRobot/wxsocketapi.h @@ -70,6 +70,8 @@ typedef enum WECHAT_HTTP_APISTag // browser WECHAT_BROWSER_OPEN_WITH_URL, WECHAT_GET_PUBLIC_MSG, + // IJ + WECHAT_MSG_FORWARD_MESSAGE, } WECHAT_HTTP_APIS, *PWECHAT_HTTP_APIS; #endif diff --git a/Python/com/test.py b/Python/com/test.py index f809ed1f99e7a6eb7bd5cf3414389fba071eeb69..ef5ebc8a40f141e9029cbd313c5bcb9c680b89f7 100644 --- a/Python/com/test.py +++ b/Python/com/test.py @@ -88,5 +88,6 @@ if __name__ == '__main__': wx = WeChatRobot(pid_list[0]) wx.StartService() wx.StartReceiveMessage() + wx.HookImageMsg(r"D:\wxdata") wxRobot.register_msg_event(pid_list[0]) wx.StopService() diff --git a/Python/com/wxRobot.py b/Python/com/wxRobot.py index 43266c42947f8c57b73ce4c403fb9c92760a6efd..7b07430b73da2a3955aa596a283a906a02a45a78 100644 --- a/Python/com/wxRobot.py +++ b/Python/com/wxRobot.py @@ -1044,6 +1044,25 @@ class WeChatRobot: pass return ret + def ForwardMessage(self,wxid:str,localId:int) -> int: + """ + 转发消息,只支持单条转发 + + Parameters + ---------- + wxid : str + 消息接收人wxid. + localId : int + 消息短id,可以在实时消息接口中获取或查询MSG{x}.db. + + Returns + ------- + int + 成功返回0,失败返回非0值. + + """ + return self.robot.CForwardMessage(self.pid,wxid,localId) + def get_wechat_pid_list() -> list: """ diff --git a/Python/http/wxDriver.py b/Python/http/wxDriver.py index 3fe48a2abf2a37df26e234902df904a0696a8c36..4978dde1cf44c9e5b55960e32e10948dd4b79564 100644 --- a/Python/http/wxDriver.py +++ b/Python/http/wxDriver.py @@ -84,6 +84,8 @@ class WECHAT_HTTP_APIS: WECHAT_BROWSER_OPEN_WITH_URL = 38 # 打开微信内置浏览器 WECHAT_GET_PUBLIC_MSG = 39 # 获取公众号历史消息 + WECHAT_MSG_FORWARD_MESSAGE = 40 # 转发消息 + APIS = WECHAT_HTTP_APIS # http api 参数模板 @@ -184,7 +186,9 @@ class WECHAT_HTTP_API_PARAM_TEMPLATES: # browser APIS.WECHAT_BROWSER_OPEN_WITH_URL: {"url": "https://www.baidu.com/"}, - APIS.WECHAT_GET_PUBLIC_MSG: {"public_id": "","offset": ""} + APIS.WECHAT_GET_PUBLIC_MSG: {"public_id": "","offset": ""}, + + APIS.WECHAT_MSG_FORWARD_MESSAGE: {"wxid": "filehelper","localId": 1}, } def get_http_template(self, api_number): diff --git a/README.md b/README.md index 6752b1f3d846013904fe0858b886d577ef59ba7b..719166942ba14809e17cd847930a115e1d0fe7c1 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,11 @@ CWeChatRobot.exe /unregserver 3. 修复了一个bug,该bug会导致图片和语音保存到微信安装目录而非指定的目录 4. 优化实时消息接口,现在会带上自己的wxid 5. 优化图片和语音保存路径,方便区分来自不同账号的消息 +## 2022.09.10 +1. 中秋节快乐 +2. 新增转发消息功能,请勿转发语音、红包等消息 +3. 实时消息接口新增`localId`字段,该字段用于转发消息接口;现在也可以接收到撤回消息提醒 +4. 优化COM连接点,在线程中进行消息广播,客户端可以阻塞以等待图片、语音等资源落地 # 打赏作者 请给作者一个star,感谢感谢 diff --git a/Release/CWeChatRobot.exe b/Release/CWeChatRobot.exe index 677443b542e55627489da184a54c8c5358c09f39..aa51ae83208a1eaf3c1e5169e3afde22b83a14c5 100644 Binary files a/Release/CWeChatRobot.exe and b/Release/CWeChatRobot.exe differ diff --git a/Release/DWeChatRobot.dll b/Release/DWeChatRobot.dll index 189e55e60cddcd00f768a301173bba410596d8ec..469af3ac4fd2dcab1e6bc72d561da66832c8b898 100644 Binary files a/Release/DWeChatRobot.dll and b/Release/DWeChatRobot.dll differ diff --git a/Release/socket/SWeChatRobot.dll b/Release/socket/SWeChatRobot.dll index 3c174448a8f0cdc9794c1db64910c1c52feef9bf..77a9934bb30fc498df82c91f53566481b8091100 100644 Binary files a/Release/socket/SWeChatRobot.dll and b/Release/socket/SWeChatRobot.dll differ diff --git a/Release/socket/wxDriver.dll b/Release/socket/wxDriver.dll index 9a7b5d3f4672a52c24c4abdaed3468b6d6b9b722..e3e8fe698f4f8c815b7a1a9aba31b61009f8f1c0 100644 Binary files a/Release/socket/wxDriver.dll and b/Release/socket/wxDriver.dll differ diff --git a/Release/socket/wxDriver64.dll b/Release/socket/wxDriver64.dll index b0f33211513c105606d5dc444aadd734b89299dc..2b2e923cacbddd4af519244921afa1157bfc7e1e 100644 Binary files a/Release/socket/wxDriver64.dll and b/Release/socket/wxDriver64.dll differ