Impl execute sql

This commit is contained in:
Changhua
2022-08-20 22:10:11 +08:00
parent 9f4ad1fba0
commit 4e7592ca1b
15 changed files with 439 additions and 70 deletions
+118 -9
View File
@@ -7,6 +7,44 @@
using namespace std;
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* Generic error */
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* Internal use only */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_FORMAT 24 /* Not used */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
#define SQLITE_INTEGER 1
#define SQLITE_FLOAT 2
#define SQLITE_TEXT 3
#define SQLITE_BLOB 4
#define SQLITE_NULL 5
extern WxCalls_t g_WxCalls;
extern DWORD g_WeChatWinDllAddr;
@@ -23,6 +61,14 @@ typedef int(__cdecl *Sqlite3_exec)(DWORD, /* The database on which th
void *, /* First argument to xCallback() */
char ** /* Write error messages here */
);
typedef int(__cdecl *Sqlite3_prepare)(DWORD, const char *, int, DWORD **, int);
typedef int(__cdecl *Sqlite3_step)(DWORD *);
typedef int(__cdecl *Sqlite3_column_count)(DWORD *);
typedef const char *(__cdecl *Sqlite3_column_name)(DWORD *, int);
typedef int(__cdecl *Sqlite3_column_type)(DWORD *, int);
typedef const void *(__cdecl *Sqlite3_column_blob)(DWORD *, int);
typedef int(__cdecl *Sqlite3_column_bytes)(DWORD *, int);
typedef int(__cdecl *Sqlite3_finalize)(DWORD *);
static int cbGetTables(void *ret, int argc, char **argv, char **azColName)
{
@@ -39,19 +85,33 @@ static int cbGetTables(void *ret, int argc, char **argv, char **azColName)
return 0;
}
dbMap_t GetDbHandles()
{
if (!dbMap.empty())
return dbMap;
g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll");
DWORD sqlHandleBaseAddr = *(DWORD *)(g_WeChatWinDllAddr + g_WxCalls.sql.base);
DWORD sqlHandleBeginAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.start);
DWORD sqlHandleEndAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.end);
while (sqlHandleBeginAddr < sqlHandleEndAddr) {
DWORD dwHandle = *(DWORD *)sqlHandleBeginAddr;
wstring dbName = wstring((wchar_t *)(*(DWORD *)(dwHandle + g_WxCalls.sql.name)));
DWORD handle = *(DWORD *)(dwHandle + g_WxCalls.sql.slot);
if (handle) {
dbMap[dbName] = handle;
}
sqlHandleBeginAddr += 0x04;
}
return dbMap;
}
vector<wstring> GetDbNames()
{
vector<wstring> vDbs;
if (dbMap.empty()) {
DWORD sqlHandleBaseAddr = *(DWORD *)(g_WeChatWinDllAddr + g_WxCalls.sql.base);
DWORD sqlHandleBeginAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.start);
DWORD sqlHandleEndAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.end);
while (sqlHandleBeginAddr < sqlHandleEndAddr) {
DWORD dwHandle = *(DWORD *)sqlHandleBeginAddr;
dbMap[wstring((wchar_t *)(*(DWORD *)(dwHandle + g_WxCalls.sql.name)))]
= *(DWORD *)(dwHandle + g_WxCalls.sql.slot);
sqlHandleBeginAddr += 0x04;
}
dbMap = GetDbHandles();
}
for (auto it = dbMap.begin(); it != dbMap.end(); it++) {
vDbs.push_back(it->first);
@@ -65,6 +125,10 @@ vector<RpcTables_t> GetDbTables(wstring db)
const char *sql = "select * from sqlite_master where type=\"table\";";
Sqlite3_exec p_Sqlite3_exec = (Sqlite3_exec)(g_WeChatWinDllAddr + g_WxCalls.sql.exec);
if (dbMap.empty()) {
dbMap = GetDbHandles();
}
auto it = dbMap.find(db);
if (it != dbMap.end()) {
p_Sqlite3_exec(it->second, sql, (sqlite3_callback)cbGetTables, &vTables, 0);
@@ -72,3 +136,48 @@ vector<RpcTables_t> GetDbTables(wstring db)
return vTables;
}
vector<vector<RpcSqlResult_t>> ExecDbQuery(wstring db, wstring sql)
{
vector<vector<RpcSqlResult_t>> vvSqlResult;
Sqlite3_prepare func_prepare = (Sqlite3_prepare)(g_WeChatWinDllAddr + 0x14227F0);
Sqlite3_step func_step = (Sqlite3_step)(g_WeChatWinDllAddr + 0x13EA780);
Sqlite3_column_count func_column_count = (Sqlite3_column_count)(g_WeChatWinDllAddr + 0x13EACD0);
Sqlite3_column_name func_column_name = (Sqlite3_column_name)(g_WeChatWinDllAddr + 0x13EB630);
Sqlite3_column_type func_column_type = (Sqlite3_column_type)(g_WeChatWinDllAddr + 0x13EB470);
Sqlite3_column_blob func_column_blob = (Sqlite3_column_blob)(g_WeChatWinDllAddr + 0x13EAD10);
Sqlite3_column_bytes func_column_bytes = (Sqlite3_column_bytes)(g_WeChatWinDllAddr + 0x13EADD0);
Sqlite3_finalize func_finalize = (Sqlite3_finalize)(g_WeChatWinDllAddr + 0x13E9730);
if (dbMap.empty()) {
dbMap = GetDbHandles();
}
DWORD *stmt;
int rc = func_prepare(dbMap[db], Wstring2String(sql).c_str(), -1, &stmt, 0);
if (rc != SQLITE_OK) {
return vvSqlResult;
}
wchar_t buffer[128] = { 0 };
while (func_step(stmt) == SQLITE_ROW) {
vector<RpcSqlResult_t> vResult;
int col_count = func_column_count(stmt);
for (int i = 0; i < col_count; i++) {
RpcSqlResult_t result = { 0 };
result.type = func_column_type(stmt, i);
result.column = GetBstrFromString(func_column_name(stmt, i));
int length = func_column_bytes(stmt, i);
const void *blob = func_column_blob(stmt, i);
if (length && (result.type != 5)) {
result.content = GetBstrFromByteArray((byte *)blob, length);
}
vResult.push_back(result);
}
vvSqlResult.push_back(vResult);
}
return vvSqlResult;
}
+1
View File
@@ -7,3 +7,4 @@
std::vector<std::wstring> GetDbNames();
std::vector<RpcTables_t> GetDbTables(std::wstring db);
std::vector<std::vector<RpcSqlResult_t>> ExecDbQuery(std::wstring db, std::wstring sql);
+93 -46
View File
@@ -22,6 +22,58 @@ extern const MsgTypesMap_t g_WxMsgTypes; // Map of WeChat Message types
static BOOL listenMsgFlag = false;
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
{
return RPC_S_OK; // Always allow anyone.
}
int RpcStartServer()
{
RPC_STATUS status;
// Uses the protocol combined with the endpoint for receiving
// 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"wcferry"), // TCP/IP port to use
NULL // No security
);
if (status)
return status;
// Registers the interface and auto listen
// Equal to RpcServerRegisterIf + RpcServerListen
status = RpcServerRegisterIf2(server_ISpy_v1_0_s_ifspec, // Interface to register.
NULL, // Use the MIDL generated entry-point vector.
NULL, // Use the MIDL generated entry-point vector.
RPC_IF_ALLOW_LOCAL_ONLY | RPC_IF_AUTOLISTEN, // Forces use of security callback.
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
(unsigned)-1, // Infinite max size of incoming data blocks.
SecurityCallback); // Naive security callback.
while (g_rpcKeepAlive) {
Sleep(1000); // 休眠,释放CPU
}
return 0;
}
int RpcStopServer()
{
RPC_STATUS status;
UnListenMessage();
listenMsgFlag = false;
g_rpcKeepAlive = false;
status = RpcMgmtStopServerListening(NULL);
if (status)
return status;
status = RpcServerUnregisterIf(server_ISpy_v1_0_s_ifspec, NULL, 0);
return status;
}
int server_IsLogin() { return IsLogin(); }
void server_EnableReceiveMsg()
@@ -179,54 +231,49 @@ int server_GetDbTables(const wchar_t *db, int *pNum, PPRpcTables *tbls)
return 0;
}
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
int server_ExecDbQuery(const wchar_t *db, const wchar_t *sql, int *pRow, int *pCol, PPPRpcSqlResult *ret)
{
return RPC_S_OK; // Always allow anyone.
}
int RpcStartServer()
{
RPC_STATUS status;
// Uses the protocol combined with the endpoint for receiving
// 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"wcferry"), // TCP/IP port to use
NULL // No security
);
if (status)
return status;
// Registers the interface and auto listen
// Equal to RpcServerRegisterIf + RpcServerListen
status = RpcServerRegisterIf2(server_ISpy_v1_0_s_ifspec, // Interface to register.
NULL, // Use the MIDL generated entry-point vector.
NULL, // Use the MIDL generated entry-point vector.
RPC_IF_ALLOW_LOCAL_ONLY | RPC_IF_AUTOLISTEN, // Forces use of security callback.
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
(unsigned)-1, // Infinite max size of incoming data blocks.
SecurityCallback); // Naive security callback.
while (g_rpcKeepAlive) {
Sleep(1000); // 休眠,释放CPU
vector<vector<RpcSqlResult_t>> vvSqlResult = ExecDbQuery(db, sql);
if (vvSqlResult.empty()) {
*pRow = *pCol = 0;
ret = NULL;
return -1;
}
*pRow = vvSqlResult.size();
*pCol = vvSqlResult[0].size();
PPPRpcSqlResult ppp = (PPPRpcSqlResult)midl_user_allocate(*pRow * sizeof(PPRpcSqlResult));
if (ppp == NULL) {
printf("server_ExecDbQuery midl_user_allocate Failed for ppp\n");
return -2;
}
for (int r = 0; r < *pRow; r++) {
PPRpcSqlResult pp = (PPRpcSqlResult)midl_user_allocate(*pCol * sizeof(PRpcSqlResult));
if (pp == NULL) {
midl_user_free(ppp);
printf("server_ExecDbQuery midl_user_allocate Failed for pp\n");
return -2;
}
for (int c = 0; c < *pCol; c++) {
PRpcSqlResult p = (PRpcSqlResult)midl_user_allocate(sizeof(RpcSqlResult_t));
if (p == NULL) {
midl_user_free(pp);
printf("server_ExecDbQuery midl_user_allocate Failed for p\n");
return -2;
}
p->type = vvSqlResult[r][c].type;
p->column = vvSqlResult[r][c].column;
p->content = vvSqlResult[r][c].content;
pp[c] = p;
}
ppp[r] = pp;
}
*ret = ppp;
return 0;
}
int RpcStopServer()
{
RPC_STATUS status;
UnListenMessage();
listenMsgFlag = false;
g_rpcKeepAlive = false;
status = RpcMgmtStopServerListening(NULL);
if (status)
return status;
status = RpcServerUnregisterIf(server_ISpy_v1_0_s_ifspec, NULL, 0);
return status;
}