Merge branch 'feat_rpc'
This commit is contained in:
commit
da5eae278c
18
App/App.cpp
18
App/App.cpp
@ -39,12 +39,6 @@ int main()
|
||||
|
||||
_wsetlocale(LC_ALL, L"chs"); // 这是个大坑,不设置中文直接不见了。。。
|
||||
|
||||
// 获取消息类型
|
||||
const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes();
|
||||
for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) {
|
||||
wprintf(L"%d: %s\n", it->first, it->second.c_str());
|
||||
}
|
||||
|
||||
wprintf(L"WxInitSDK: ");
|
||||
status = WxInitSDK();
|
||||
wcout << status << endl;
|
||||
@ -53,18 +47,26 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取消息类型
|
||||
wprintf(L"获取消息类型\n");
|
||||
const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes();
|
||||
for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) {
|
||||
wprintf(L"%d: %s\n", it->first, it->second.c_str());
|
||||
}
|
||||
|
||||
wprintf(L"Message: 接收通知中......\n");
|
||||
WxSetTextMsgCb(onTextMsg);
|
||||
Sleep(1000); // 等待1秒
|
||||
|
||||
// 测试发送消息
|
||||
wprintf(L"测试发送消息\n");
|
||||
WxSendTextMsg(wxid, at_wxid, content);
|
||||
Sleep(1000); // 等待1秒
|
||||
|
||||
// 测试发送照片
|
||||
wprintf(L"测试发送照片\n");
|
||||
WxSendImageMsg(wxid, img_path);
|
||||
|
||||
Sleep(10000); // 等待10秒
|
||||
Sleep(1000); // 等待1秒
|
||||
|
||||
// 测试获取联系人
|
||||
auto mContact = WxGetContacts();
|
||||
|
38
Rpc/rpc.idl
38
Rpc/rpc.idl
@ -1,4 +1,4 @@
|
||||
[
|
||||
[
|
||||
uuid(ed838ecd-8a1e-4da7-bfda-9f2d12d07893),
|
||||
version(1.0),
|
||||
implicit_handle(handle_t hSpyBinding),
|
||||
@ -6,12 +6,44 @@
|
||||
|
||||
interface ISpy
|
||||
{
|
||||
import "rpc_types.h";
|
||||
import "oaidl.idl";
|
||||
|
||||
typedef struct RpcMessage {
|
||||
int self; // 是否自己发的消息:0=否,1=是
|
||||
int type; // 消息类型
|
||||
int source; // 消息来源:0=好友消息,1=群消息
|
||||
BSTR id; // 消息ID
|
||||
BSTR xml; // 群其他消息
|
||||
BSTR wxId; // 发送人微信ID
|
||||
BSTR roomId; // 群ID
|
||||
BSTR content; // 消息内容,MAC版最大:16384,即16KB
|
||||
} RpcMessage_t;
|
||||
|
||||
typedef struct RpcIntBstrPair {
|
||||
int key;
|
||||
BSTR value;
|
||||
} RpcIntBstrPair_t;
|
||||
typedef RpcIntBstrPair_t* PRpcIntBstrPair;
|
||||
typedef RpcIntBstrPair_t** PPRpcIntBstrPair;
|
||||
|
||||
typedef struct RpcContact {
|
||||
BSTR wxId;
|
||||
BSTR wxCode;
|
||||
BSTR wxName;
|
||||
BSTR wxCountry;
|
||||
BSTR wxProvince;
|
||||
BSTR wxCity;
|
||||
BSTR wxGender;
|
||||
} RpcContact_t;
|
||||
typedef RpcContact_t *PRpcContact;
|
||||
typedef RpcContact_t **PPRpcContact;
|
||||
|
||||
int IsLogin();
|
||||
int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg);
|
||||
int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path);
|
||||
int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes);
|
||||
int GetContacts([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts);
|
||||
|
||||
void EnableReceiveMsg();
|
||||
[callback] int ReceiveMsg([ in ] RpcMessage_t *msg);
|
||||
[callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
|
||||
};
|
||||
|
@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define MSG_SIZE_MSG_ID 64
|
||||
#define MSG_SIZE_MSG_XML 4096
|
||||
#define MSG_SIZE_WXID 64
|
||||
#define MSG_SIZE_ROOMID 64
|
||||
#define MSG_SIZE_CONTENT 16385
|
||||
|
||||
typedef struct RpcMessage {
|
||||
int self; // 是否自己发的消息:0=否,1=是
|
||||
int type; // 消息类型
|
||||
int source; // 消息来源:0=好友消息,1=群消息
|
||||
wchar_t id[MSG_SIZE_MSG_ID]; // 消息ID
|
||||
wchar_t xml[MSG_SIZE_MSG_XML]; // 群其他消息
|
||||
wchar_t wxId[MSG_SIZE_WXID]; // 发送人微信ID
|
||||
wchar_t roomId[MSG_SIZE_ROOMID]; // 群ID
|
||||
wchar_t content[MSG_SIZE_CONTENT]; // 消息内容,MAC版最大:16384,即16KB
|
||||
} RpcMessage_t;
|
@ -119,6 +119,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -161,6 +162,7 @@
|
||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="injector.h" />
|
||||
<ClInclude Include="rpc_client.h" />
|
||||
<ClInclude Include="sdk.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
</ItemGroup>
|
||||
@ -169,6 +171,7 @@
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="injector.cpp" />
|
||||
<ClCompile Include="rpc_client.cpp" />
|
||||
<ClCompile Include="sdk.cpp" />
|
||||
<ClCompile Include="util.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -30,6 +30,9 @@
|
||||
<ClInclude Include="injector.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpc_client.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
@ -50,6 +53,9 @@
|
||||
<ClCompile Include="injector.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpc_client.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="sdk.def">
|
||||
|
167
SDK/rpc_client.cpp
Normal file
167
SDK/rpc_client.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include "rpc_client.h"
|
||||
#include "sdk.h"
|
||||
#include "util.h"
|
||||
|
||||
static RPC_WSTR pszStringBinding = NULL;
|
||||
extern std::function<int(WxMessage_t)> g_cbReceiveTextMsg;
|
||||
|
||||
RPC_STATUS RpcConnectServer()
|
||||
{
|
||||
RPC_STATUS status = 0;
|
||||
// Creates a string binding handle.
|
||||
status = RpcStringBindingCompose(NULL, // UUID to bind to
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||
NULL, // TCP/IP network address to use
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"wcferry"), // TCP/IP port to use
|
||||
NULL, // Protocol dependent network options to use
|
||||
&pszStringBinding); // String binding output
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Validates the format of the string binding handle and converts it to a binding handle.
|
||||
pszStringBinding: The string binding to validate
|
||||
hSpyBinding: Put the result in the implicit binding(defined in the IDL file)
|
||||
*/
|
||||
status = RpcBindingFromStringBinding(pszStringBinding, &hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
RPC_STATUS RpcDisconnectServer()
|
||||
{
|
||||
RPC_STATUS status;
|
||||
// Free the memory allocated by a string
|
||||
status = RpcStringFree(&pszStringBinding);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
// Releases binding handle resources and disconnects from the server
|
||||
status = RpcBindingFree(&hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned int __stdcall RpcSetTextMsgCb(void *p)
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出)
|
||||
client_EnableReceiveMsg();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("rpcWxSetTextMsgCb exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RpcIsLogin()
|
||||
{
|
||||
int loginFlag = 0;
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// 查询登录状态
|
||||
loginFlag = client_IsLogin();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("rpcIsLogin exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return loginFlag;
|
||||
}
|
||||
|
||||
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendTextMsg(wxid, at_wxid, msg); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("rpcWxSendTextMsg exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendImageMsg(wxid, path); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("rpcWxSendImageMsg exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
PPRpcIntBstrPair ppRpcMsgTypes = NULL;
|
||||
|
||||
RpcTryExcept { ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcGetMsgTypes exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
if (ret != 0) {
|
||||
printf("GetMsgTypes Failed: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ppRpcMsgTypes;
|
||||
}
|
||||
|
||||
PPRpcContact RpcGetContacts(int *pNum)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
PPRpcContact ppRpcContacts = NULL;
|
||||
|
||||
RpcTryExcept { ret = client_GetContacts(pNum, &ppRpcContacts); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcGetContacts exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
if (ret != 0) {
|
||||
printf("GetContacts Failed: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ppRpcContacts;
|
||||
}
|
||||
|
||||
int server_ReceiveMsg(RpcMessage_t rpcMsg)
|
||||
{
|
||||
WxMessage_t msg;
|
||||
GetRpcMessage(&msg, rpcMsg);
|
||||
try {
|
||||
g_cbReceiveTextMsg(msg); // 调用接收消息回调
|
||||
} catch (...) {
|
||||
printf("callback error...\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
13
SDK/rpc_client.h
Normal file
13
SDK/rpc_client.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "rpc_h.h"
|
||||
|
||||
RPC_STATUS RpcConnectServer();
|
||||
RPC_STATUS RpcDisconnectServer();
|
||||
|
||||
unsigned int __stdcall RpcSetTextMsgCb(void *p);
|
||||
int RpcIsLogin();
|
||||
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg);
|
||||
int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path);
|
||||
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum);
|
||||
PPRpcContact RpcGetContacts(int *pNum);
|
258
SDK/sdk.cpp
258
SDK/sdk.cpp
@ -7,87 +7,25 @@
|
||||
#include <tlhelp32.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../Rpc/rpc_h.h"
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
|
||||
#include "injector.h"
|
||||
#include "rpc_types.h"
|
||||
#include "rpc_client.h"
|
||||
#include "sdk.h"
|
||||
#include "util.h"
|
||||
|
||||
static HANDLE hEvent;
|
||||
static std::queue<RpcMessage_t> MsgQueue;
|
||||
static RPC_WSTR pszStringBinding = NULL;
|
||||
static std::function<int(WxMessage_t)> cbReceiveTextMsg;
|
||||
static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" },
|
||||
{ 0x03, L"图片" },
|
||||
{ 0x22, L"语音" },
|
||||
{ 0x25, L"好友确认" },
|
||||
{ 0x28, L"POSSIBLEFRIEND_MSG" },
|
||||
{ 0x2A, L"名片" },
|
||||
{ 0x2B, L"视频" },
|
||||
{ 0x2F, L"石头剪刀布 | 表情图片" },
|
||||
{ 0x30, L"位置" },
|
||||
{ 0x31, L"共享实时位置、文件、转账、链接" },
|
||||
{ 0x32, L"VOIPMSG" },
|
||||
{ 0x33, L"微信初始化" },
|
||||
{ 0x34, L"VOIPNOTIFY" },
|
||||
{ 0x35, L"VOIPINVITE" },
|
||||
{ 0x3E, L"小视频" },
|
||||
{ 0x270F, L"SYSNOTICE" },
|
||||
{ 0x2710, L"红包、系统消息" },
|
||||
{ 0x2712, L"撤回消息" } };
|
||||
|
||||
RPC_STATUS RpcConnectServer()
|
||||
{
|
||||
RPC_STATUS status = 0;
|
||||
// Creates a string binding handle.
|
||||
status = RpcStringBindingCompose(NULL, // UUID to bind to
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||
NULL, // TCP/IP network address to use
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
|
||||
NULL, // Protocol dependent network options to use
|
||||
&pszStringBinding); // String binding output
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Validates the format of the string binding handle and converts it to a binding handle.
|
||||
pszStringBinding: The string binding to validate
|
||||
hSpyBinding: Put the result in the implicit binding(defined in the IDL file)
|
||||
*/
|
||||
status = RpcBindingFromStringBinding(pszStringBinding, &hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
RPC_STATUS RpcDisconnectServer()
|
||||
{
|
||||
RPC_STATUS status;
|
||||
// Free the memory allocated by a string
|
||||
status = RpcStringFree(&pszStringBinding);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
// Releases binding handle resources and disconnects from the server
|
||||
status = RpcBindingFree(&hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
std::function<int(WxMessage_t)> g_cbReceiveTextMsg;
|
||||
|
||||
int WxInitSDK()
|
||||
{
|
||||
int loginFlag = 0;
|
||||
unsigned long ulCode = 0;
|
||||
DWORD status = 0;
|
||||
DWORD pid = 0;
|
||||
WCHAR DllPath[MAX_PATH] = { 0 };
|
||||
|
||||
GetModuleFileNameW(GetModuleHandleW(WECHATSDKDLL), DllPath, MAX_PATH);
|
||||
PathRemoveFileSpecW(DllPath);
|
||||
PathAppendW(DllPath, WECHATINJECTDLL);
|
||||
GetModuleFileName(GetModuleHandle(WECHATSDKDLL), DllPath, MAX_PATH);
|
||||
PathRemoveFileSpec(DllPath);
|
||||
PathAppend(DllPath, WECHATINJECTDLL);
|
||||
|
||||
if (!PathFileExistsW(DllPath)) {
|
||||
if (!PathFileExists(DllPath)) {
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -102,88 +40,20 @@ int WxInitSDK()
|
||||
|
||||
RpcConnectServer();
|
||||
|
||||
while (!loginFlag) {
|
||||
RpcTryExcept
|
||||
{
|
||||
// 查询登录状态
|
||||
loginFlag = client_IsLogin();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
while (!RpcIsLogin()) {
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned int __stdcall waitForMsg(void *p)
|
||||
{
|
||||
RpcMessage_t *rpcMsg;
|
||||
while (true) {
|
||||
// 中断式,兼顾及时性和CPU使用率
|
||||
WaitForSingleObject(hEvent, INFINITE); // 等待消息
|
||||
while (!MsgQueue.empty()) {
|
||||
rpcMsg = (RpcMessage_t *)&MsgQueue.front();
|
||||
WxMessage_t msg;
|
||||
msg.id = wstring(rpcMsg->id);
|
||||
msg.self = rpcMsg->self;
|
||||
msg.type = rpcMsg->type;
|
||||
msg.source = rpcMsg->source;
|
||||
msg.xml = wstring(rpcMsg->xml);
|
||||
msg.wxId = wstring(rpcMsg->wxId);
|
||||
msg.roomId = wstring(rpcMsg->roomId);
|
||||
msg.content = wstring(rpcMsg->content);
|
||||
|
||||
try {
|
||||
cbReceiveTextMsg(msg); // 调用接收消息回调
|
||||
} catch (...) {
|
||||
printf("callback error...\n");
|
||||
}
|
||||
MsgQueue.pop();
|
||||
}
|
||||
ResetEvent(hEvent);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int __stdcall innerWxSetTextMsgCb(void *p)
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出)
|
||||
client_EnableReceiveMsg();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
|
||||
{
|
||||
if (onMsg) {
|
||||
HANDLE msgThread;
|
||||
cbReceiveTextMsg = onMsg;
|
||||
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
msgThread = (HANDLE)_beginthreadex(NULL, 0, waitForMsg, NULL, 0, NULL);
|
||||
if (msgThread == NULL) {
|
||||
printf("Failed to create message listening thread.\n");
|
||||
return -2;
|
||||
}
|
||||
CloseHandle(msgThread);
|
||||
g_cbReceiveTextMsg = onMsg;
|
||||
|
||||
msgThread = (HANDLE)_beginthreadex(NULL, 0, innerWxSetTextMsgCb, NULL, 0, NULL);
|
||||
msgThread = (HANDLE)_beginthreadex(NULL, 0, RpcSetTextMsgCb, NULL, 0, NULL);
|
||||
if (msgThread == NULL) {
|
||||
printf("Failed to create innerWxRecvTextMsg.\n");
|
||||
return -2;
|
||||
@ -197,51 +67,12 @@ int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int server_ReceiveMsg(RpcMessage_t *rpcMsg)
|
||||
{
|
||||
MsgQueue.push(*rpcMsg); // 发送消息
|
||||
SetEvent(hEvent); // 发送消息通知
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int innerWxSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendTextMsg(wxid, at_wxid, msg); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WxSendTextMsg(wstring wxid, wstring at_wxid, wstring msg)
|
||||
{
|
||||
return innerWxSendTextMsg(wxid.c_str(), at_wxid.c_str(), msg.c_str());
|
||||
return RpcSendTextMsg(wxid.c_str(), at_wxid.c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
static int innerWxSendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendImageMsg(wxid, path); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WxSendImageMsg(wstring wxid, wstring path) { return innerWxSendImageMsg(wxid.c_str(), path.c_str()); }
|
||||
int WxSendImageMsg(wstring wxid, wstring path) { return RpcSendImageMsg(wxid.c_str(), path.c_str()); }
|
||||
|
||||
static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
||||
{
|
||||
@ -297,45 +128,46 @@ static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
MsgTypesMap_t WxGetMsgTypes()
|
||||
{
|
||||
static MsgTypesMap_t WxMsgTypes;
|
||||
if (WxMsgTypes.empty()) {
|
||||
int size = 0;
|
||||
PPRpcIntBstrPair pp = RpcGetMsgTypes(&size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value)));
|
||||
midl_user_free(pp[i]);
|
||||
}
|
||||
if (pp) {
|
||||
midl_user_free(pp);
|
||||
}
|
||||
}
|
||||
|
||||
return WxMsgTypes;
|
||||
}
|
||||
|
||||
ContactMap_t WxGetContacts()
|
||||
{
|
||||
ContactMap_t mContact;
|
||||
DWORD moduleBaseAddress;
|
||||
HANDLE hProcess;
|
||||
int size = 0;
|
||||
PPRpcContact pp = RpcGetContacts(&size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
WxContact_t contact;
|
||||
contact.wxId = GetWstringFromBstr(pp[i]->wxId);
|
||||
contact.wxCode = GetWstringFromBstr(pp[i]->wxCode);
|
||||
contact.wxName = GetWstringFromBstr(pp[i]->wxName);
|
||||
contact.wxCountry = GetWstringFromBstr(pp[i]->wxCountry);
|
||||
contact.wxProvince = GetWstringFromBstr(pp[i]->wxProvince);
|
||||
contact.wxCity = GetWstringFromBstr(pp[i]->wxCity);
|
||||
contact.wxGender = GetWstringFromBstr(pp[i]->wxGender);
|
||||
|
||||
if (getAddrHandle(&moduleBaseAddress, &hProcess) != 0) {
|
||||
return mContact;
|
||||
}
|
||||
printf("WxGetContacts\n");
|
||||
DWORD baseAddr = moduleBaseAddress + 0x23638F4;
|
||||
DWORD tempAddr = GetMemoryIntByAddress(hProcess, baseAddr);
|
||||
DWORD head = GetMemoryIntByAddress(hProcess, tempAddr + 0x4C);
|
||||
DWORD node = GetMemoryIntByAddress(hProcess, head);
|
||||
|
||||
while (node != head) {
|
||||
WxContact_t contactItem;
|
||||
contactItem.wxId = GetUnicodeInfoByAddress(hProcess, node + 0x30);
|
||||
contactItem.wxCode = GetUnicodeInfoByAddress(hProcess, node + 0x44);
|
||||
contactItem.wxName = GetUnicodeInfoByAddress(hProcess, node + 0x8C);
|
||||
contactItem.wxCountry = GetUnicodeInfoByAddress(hProcess, node + 0x1D0);
|
||||
contactItem.wxProvince = GetUnicodeInfoByAddress(hProcess, node + 0x1E4);
|
||||
contactItem.wxCity = GetUnicodeInfoByAddress(hProcess, node + 0x1F8);
|
||||
DWORD gender = GetMemoryIntByAddress(hProcess, node + 0x184);
|
||||
|
||||
if (gender == 1)
|
||||
contactItem.wxGender = L"男";
|
||||
else if (gender == 2)
|
||||
contactItem.wxGender = L"女";
|
||||
else
|
||||
contactItem.wxGender = L"未知";
|
||||
|
||||
mContact.insert(make_pair(contactItem.wxId, contactItem));
|
||||
node = GetMemoryIntByAddress(hProcess, node);
|
||||
mContact.insert(make_pair(contact.wxId, contact));
|
||||
midl_user_free(pp[i]);
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
if (pp) {
|
||||
midl_user_free(pp);
|
||||
}
|
||||
|
||||
return mContact;
|
||||
}
|
||||
|
||||
MsgTypesMap_t WxGetMsgTypes() { return WxMsgTypes; }
|
||||
|
41
SDK/util.cpp
41
SDK/util.cpp
@ -133,17 +133,16 @@ int OpenWeChat(DWORD *pid)
|
||||
{
|
||||
int ret = -1;
|
||||
STARTUPINFO si = { sizeof(si) };
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
ret = GetWeChatPath(Path);
|
||||
if (ERROR_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||||
ret = GetLastError();
|
||||
return ret;
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
@ -151,9 +150,7 @@ int OpenWeChat(DWORD *pid)
|
||||
|
||||
*pid = pi.dwProcessId;
|
||||
|
||||
ret = ERROR_SUCCESS;
|
||||
|
||||
return ret;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
||||
@ -170,6 +167,38 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
||||
return strLength;
|
||||
}
|
||||
|
||||
BSTR GetBstrByAddress(DWORD address)
|
||||
{
|
||||
wchar_t *p = GET_WSTRING(address);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4));
|
||||
}
|
||||
|
||||
wstring GetWstringFromBstr(BSTR p)
|
||||
{
|
||||
wstring ws = L"";
|
||||
if (p != NULL) {
|
||||
ws = wstring(p);
|
||||
SysFreeString(p);
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg)
|
||||
{
|
||||
wxMsg->self = rpcMsg.self;
|
||||
wxMsg->type = rpcMsg.type;
|
||||
wxMsg->source = rpcMsg.source;
|
||||
wxMsg->id = GetWstringFromBstr(rpcMsg.id);
|
||||
wxMsg->xml = GetWstringFromBstr(rpcMsg.xml);
|
||||
wxMsg->wxId = GetWstringFromBstr(rpcMsg.wxId);
|
||||
wxMsg->roomId = GetWstringFromBstr(rpcMsg.roomId);
|
||||
wxMsg->content = GetWstringFromBstr(rpcMsg.content);
|
||||
}
|
||||
|
||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
|
||||
{
|
||||
DWORD value = 0;
|
||||
|
@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "sdk.h"
|
||||
#include "rpc_h.h"
|
||||
|
||||
#define WECHAREXE L"WeChat.exe"
|
||||
#define WECHATWINDLL L"WeChatWin.dll"
|
||||
#define WECHATSDKDLL L"SDK.dll"
|
||||
@ -17,5 +20,8 @@ int GetWeChatWinDLLPath(wchar_t *path);
|
||||
int GetWeChatVersion(wchar_t *version);
|
||||
bool GetFileVersion(const wchar_t *filePath, wchar_t *version);
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size);
|
||||
BSTR GetBstrByAddress(DWORD address);
|
||||
void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg);
|
||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address);
|
||||
std::wstring GetWstringFromBstr(BSTR p);
|
||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
||||
|
@ -122,6 +122,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<Midl>
|
||||
<AdditionalOptions>/prefix client "client_" server "server_" </AdditionalOptions>
|
||||
@ -163,10 +164,10 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Rpc\rpc_types.h" />
|
||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||
<ClInclude Include="..\SDK\util.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="get_contacts.h" />
|
||||
<ClInclude Include="load_calls.h" />
|
||||
<ClInclude Include="monitor.h" />
|
||||
<ClInclude Include="receive_msg.h" />
|
||||
@ -179,6 +180,7 @@
|
||||
<ClCompile Include="..\Rpc\rpc_s.c" />
|
||||
<ClCompile Include="..\SDK\util.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="get_contacts.cpp" />
|
||||
<ClCompile Include="load_calls.cpp" />
|
||||
<ClCompile Include="monitor.cpp" />
|
||||
<ClCompile Include="receive_msg.cpp" />
|
||||
|
@ -27,9 +27,6 @@
|
||||
<ClInclude Include="monitor.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Rpc\rpc_types.h">
|
||||
<Filter>Rpc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpc_server.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
@ -48,6 +45,9 @@
|
||||
<ClInclude Include="spy_types.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="get_contacts.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
@ -77,6 +77,9 @@
|
||||
<ClCompile Include="send_msg.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="get_contacts.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\Rpc\rpc.idl">
|
||||
|
39
Spy/get_contacts.cpp
Normal file
39
Spy/get_contacts.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "get_contacts.h"
|
||||
#include "load_calls.h"
|
||||
#include "util.h"
|
||||
|
||||
extern WxCalls_t g_WxCalls;
|
||||
extern DWORD g_WeChatWinDllAddr;
|
||||
|
||||
std::vector<RpcContact_t> GetContacts()
|
||||
{
|
||||
int gender = 0;
|
||||
vector<RpcContact_t> vContacts;
|
||||
DWORD baseAddr = g_WeChatWinDllAddr + g_WxCalls.contact.base;
|
||||
DWORD tempAddr = GET_DWORD(baseAddr);
|
||||
DWORD head = GET_DWORD(tempAddr + g_WxCalls.contact.head);
|
||||
DWORD node = GET_DWORD(head);
|
||||
|
||||
while (node != head) {
|
||||
RpcContact_t rpcContact = { 0 };
|
||||
rpcContact.wxId = GetBstrByAddress(node + g_WxCalls.contact.wxId);
|
||||
rpcContact.wxCode = GetBstrByAddress(node + g_WxCalls.contact.wxCode);
|
||||
rpcContact.wxName = GetBstrByAddress(node + g_WxCalls.contact.wxName);
|
||||
rpcContact.wxCountry = GetBstrByAddress(node + g_WxCalls.contact.wxCountry);
|
||||
rpcContact.wxProvince = GetBstrByAddress(node + g_WxCalls.contact.wxProvince);
|
||||
rpcContact.wxCity = GetBstrByAddress(node + g_WxCalls.contact.wxCity);
|
||||
|
||||
gender = GET_DWORD(node + g_WxCalls.contact.wxGender);
|
||||
if (gender == 1)
|
||||
rpcContact.wxGender = SysAllocString(L"男");
|
||||
else if (gender == 2)
|
||||
rpcContact.wxGender = SysAllocString(L"女");
|
||||
else
|
||||
rpcContact.wxGender = SysAllocString(L"未知");
|
||||
|
||||
vContacts.push_back(rpcContact);
|
||||
node = GET_DWORD(node);
|
||||
}
|
||||
|
||||
return vContacts;
|
||||
}
|
7
Spy/get_contacts.h
Normal file
7
Spy/get_contacts.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "rpc_h.h"
|
||||
|
||||
std::vector<RpcContact_t> GetContacts();
|
@ -4,17 +4,18 @@
|
||||
#include "load_calls.h"
|
||||
|
||||
#define SUPPORT_VERSION L"3.7.0.29"
|
||||
WxCalls_t wxCalls = {
|
||||
0x23631D0, // Login Status
|
||||
WxCalls_t wxCalls = { 0x23631D0, // Login Status
|
||||
{ 0x236307C, 0x23630F4, 0x2363128 }, // User Info: wxid, nickname, mobile
|
||||
0x521D30, // Send Message
|
||||
/* Receive Message:
|
||||
Hook, call, type, self, id, msgXml, roomId, wxId, content */
|
||||
{ 0x550F4C, 0xA94A50, 0x38, 0x3C, 0x184, 0x1EC, 0x48, 0x170, 0x70 },
|
||||
{ 0xBD780, 0x770120, 0x521640 } // Send Image Message
|
||||
};
|
||||
{ 0xBD780, 0x770120, 0x521640 }, // Send Image Message
|
||||
/* Get Contacts:
|
||||
Base, head, wxId, Code, Name, Gender, Country, Province, City*/
|
||||
{ 0x23638F4, 0x4C, 0x30, 0x44, 0x8C, 0x184, 0x1D0, 0x1E4, 0x1F8 } };
|
||||
|
||||
int LoadCalls(const wchar_t* version, WxCalls_t* calls)
|
||||
int LoadCalls(const wchar_t *version, WxCalls_t *calls)
|
||||
{
|
||||
if (wcscmp(version, SUPPORT_VERSION) != 0) {
|
||||
return -1;
|
||||
|
@ -14,30 +14,50 @@ MsgQueue_t g_MsgQueue;
|
||||
DWORD reg_buffer = 0;
|
||||
DWORD recvMsgCallAddr = 0;
|
||||
DWORD recvMsgJumpBackAddr = 0;
|
||||
RpcMessage_t *pMsg = NULL; // Find a palce to free
|
||||
RpcMessage_t lMsg = { 0 };
|
||||
|
||||
extern const MsgTypesMap_t g_WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" },
|
||||
{ 0x03, L"图片" },
|
||||
{ 0x22, L"语音" },
|
||||
{ 0x25, L"好友确认" },
|
||||
{ 0x28, L"POSSIBLEFRIEND_MSG" },
|
||||
{ 0x2A, L"名片" },
|
||||
{ 0x2B, L"视频" },
|
||||
{ 0x2F, L"石头剪刀布 | 表情图片" },
|
||||
{ 0x30, L"位置" },
|
||||
{ 0x31, L"共享实时位置、文件、转账、链接" },
|
||||
{ 0x32, L"VOIPMSG" },
|
||||
{ 0x33, L"微信初始化" },
|
||||
{ 0x34, L"VOIPNOTIFY" },
|
||||
{ 0x35, L"VOIPINVITE" },
|
||||
{ 0x3E, L"小视频" },
|
||||
{ 0x270F, L"SYSNOTICE" },
|
||||
{ 0x2710, L"红包、系统消息" },
|
||||
{ 0x2712, L"撤回消息" } };
|
||||
|
||||
void DispatchMsg(DWORD reg)
|
||||
{
|
||||
DWORD *p = (DWORD *)reg; //消息结构基址
|
||||
DWORD* p = (DWORD*)reg; //消息结构基址
|
||||
|
||||
memset(pMsg, 0, sizeof(RpcMessage_t));
|
||||
memset(&lMsg, 0, sizeof(RpcMessage_t));
|
||||
|
||||
pMsg->type = GET_DWORD(*p + g_WxCalls.recvMsg.type);
|
||||
pMsg->self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf);
|
||||
lMsg.type = GET_DWORD(*p + g_WxCalls.recvMsg.type);
|
||||
lMsg.self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf);
|
||||
lMsg.id = GetBstrByAddress(*p + g_WxCalls.recvMsg.msgId);
|
||||
lMsg.xml = GetBstrByAddress(*p + g_WxCalls.recvMsg.msgXml);
|
||||
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.msgId, pMsg->id, MSG_SIZE_MSG_ID);
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.msgXml, pMsg->xml, MSG_SIZE_MSG_XML);
|
||||
|
||||
if (wcsstr(pMsg->xml, L"<membercount>") == NULL) {
|
||||
if (wcsstr(lMsg.xml, L"<membercount>") == NULL) {
|
||||
// pMsg.roomId = {0};
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.roomId, pMsg->wxId, MSG_SIZE_WXID);
|
||||
} else {
|
||||
pMsg->source = 1;
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.roomId, pMsg->roomId, MSG_SIZE_ROOMID);
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.wxId, pMsg->wxId, MSG_SIZE_WXID);
|
||||
lMsg.wxId = GetBstrByAddress(*p + g_WxCalls.recvMsg.roomId);
|
||||
}
|
||||
GetWstringByAddress(*p + g_WxCalls.recvMsg.content, pMsg->content, MSG_SIZE_CONTENT);
|
||||
g_MsgQueue.push(*pMsg); // 发送消息
|
||||
else {
|
||||
lMsg.source = 1;
|
||||
lMsg.wxId = GetBstrByAddress(*p + g_WxCalls.recvMsg.wxId);
|
||||
lMsg.roomId = GetBstrByAddress(*p + g_WxCalls.recvMsg.roomId);
|
||||
}
|
||||
lMsg.content = GetBstrByAddress(*p + g_WxCalls.recvMsg.content);
|
||||
g_MsgQueue.push(lMsg); // 发送消息
|
||||
SetEvent(g_hEvent); // 发送消息通知
|
||||
}
|
||||
|
||||
@ -63,7 +83,6 @@ void ListenMessage()
|
||||
return;
|
||||
}
|
||||
|
||||
pMsg = new RpcMessage_t;
|
||||
DWORD hookAddress = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook;
|
||||
recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call;
|
||||
recvMsgJumpBackAddr = hookAddress + 5;
|
||||
|
@ -1,16 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "get_contacts.h"
|
||||
#include "monitor.h"
|
||||
#include "rpc_h.h"
|
||||
#include "rpc_server.h"
|
||||
#include "sdk.h"
|
||||
#include "send_msg.h"
|
||||
#include "spy_types.h"
|
||||
|
||||
#include "../Rpc/rpc_h.h"
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
|
||||
extern HANDLE g_hEvent;
|
||||
extern MsgQueue_t g_MsgQueue;
|
||||
extern const MsgTypesMap_t g_WxMsgTypes;
|
||||
|
||||
int server_IsLogin() { return IsLogin(); }
|
||||
|
||||
@ -25,7 +26,7 @@ void server_EnableReceiveMsg()
|
||||
// 中断式,兼顾及时性和CPU使用率
|
||||
WaitForSingleObject(g_hEvent, INFINITE); // 等待消息
|
||||
while (!g_MsgQueue.empty()) {
|
||||
client_ReceiveMsg((RpcMessage_t *)&g_MsgQueue.front()); // 调用接收消息回调
|
||||
client_ReceiveMsg(g_MsgQueue.front()); // 调用接收消息回调
|
||||
g_MsgQueue.pop();
|
||||
}
|
||||
ResetEvent(g_hEvent);
|
||||
@ -34,7 +35,7 @@ void server_EnableReceiveMsg()
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
printf("server_EnableReceiveMsg exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
@ -53,6 +54,67 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes)
|
||||
{
|
||||
*pNum = g_WxMsgTypes.size();
|
||||
PPRpcIntBstrPair pp = (PPRpcIntBstrPair)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t));
|
||||
if (pp == NULL) {
|
||||
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
|
||||
return -2;
|
||||
}
|
||||
int index = 0;
|
||||
for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); it++) {
|
||||
PRpcIntBstrPair p = (PRpcIntBstrPair)midl_user_allocate(sizeof(RpcIntBstrPair_t));
|
||||
if (p == NULL) {
|
||||
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
p->key = it->first;
|
||||
p->value = SysAllocString(it->second.c_str());
|
||||
pp[index++] = p;
|
||||
}
|
||||
|
||||
*msgTypes = pp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int server_GetContacts(int *pNum, PPRpcContact *contacts)
|
||||
{
|
||||
std::vector<RpcContact_t> vContacts = GetContacts();
|
||||
|
||||
*pNum = vContacts.size();
|
||||
PPRpcContact pp = (PPRpcContact)midl_user_allocate(*pNum * sizeof(RpcContact_t));
|
||||
if (pp == NULL) {
|
||||
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (auto it = vContacts.begin(); it != vContacts.end(); it++) {
|
||||
PRpcContact p = (PRpcContact)midl_user_allocate(sizeof(RpcContact_t));
|
||||
if (p == NULL) {
|
||||
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
p->wxId = it->wxId;
|
||||
p->wxCode = it->wxCode;
|
||||
p->wxName = it->wxName;
|
||||
p->wxCountry = it->wxCountry;
|
||||
p->wxProvince = it->wxProvince;
|
||||
p->wxCity = it->wxCity;
|
||||
p->wxGender = it->wxGender;
|
||||
|
||||
pp[index++] = p;
|
||||
}
|
||||
|
||||
*contacts = pp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
|
||||
{
|
||||
return RPC_S_OK; // Always allow anyone.
|
||||
@ -65,7 +127,7 @@ int RpcStartServer(HMODULE hModule)
|
||||
// remote procedure calls.
|
||||
status = RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Backlog queue length for TCP/IP.
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
|
||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"wcferry"), // TCP/IP port to use
|
||||
NULL // No security
|
||||
);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "framework.h"
|
||||
#include <queue>
|
||||
|
||||
#include "rpc_types.h"
|
||||
#include "rpc_h.h"
|
||||
|
||||
typedef struct UserInfoCall {
|
||||
DWORD wxid;
|
||||
@ -19,7 +19,7 @@ typedef struct RecvMsg {
|
||||
DWORD msgId; // 消息ID地址
|
||||
DWORD msgXml; // 消息xml内容地址
|
||||
DWORD roomId; // 群聊时,为群ID;私聊时,为微信ID
|
||||
DWORD wxId; // 私聊时,为空;群群时,为发送者微信ID
|
||||
DWORD wxId; // 私聊时,为空;群聊时,为发送者微信ID
|
||||
DWORD content; // 消息内容地址
|
||||
} RecvMsg_t;
|
||||
|
||||
@ -29,12 +29,25 @@ typedef struct SendImg {
|
||||
DWORD call3;
|
||||
} SendImg_t;
|
||||
|
||||
typedef struct Contact {
|
||||
DWORD base;
|
||||
DWORD head;
|
||||
DWORD wxId;
|
||||
DWORD wxCode;
|
||||
DWORD wxName;
|
||||
DWORD wxGender;
|
||||
DWORD wxCountry;
|
||||
DWORD wxProvince;
|
||||
DWORD wxCity;
|
||||
} Contact_t;
|
||||
|
||||
typedef struct WxCalls {
|
||||
DWORD login; // 登录状态
|
||||
UserInfoCall_t ui; // 用户信息
|
||||
DWORD sendTextMsg; // 发送消息
|
||||
RecvMsg_t recvMsg; // 接收消息
|
||||
SendImg_t sendImg; // 发送图片
|
||||
Contact_t contact; // 获取联系人
|
||||
} WxCalls_t;
|
||||
|
||||
typedef struct TextStruct {
|
||||
|
Loading…
Reference in New Issue
Block a user