前言:Windows自带的RPC通信在通过LPC处理时有很多不足之处,例如不支持参数传入传出指针是一件很不幸的事情,以下是一个简单自定义LPC框架,暂不支持网络调用;
/**********************************AlLocalProcedureCall.h**********************************/
#pragma once
#define PAGE_SIZE (4096U)
#pragma pack(1)
//本地函数调用数据结构
typedef struct _GLOBAL_FUNCTION_TABLE {
DWORD dwClientId; //客服进程ID
DWORD dwServerId; //服务进程ID
HANDLE hMapObject; //映射句柄
UINT uIsAccessOpera; //正被访问
VOID * pBaseParamData; //参数内存地址
DWORD dwBaseParamSize; //参数内存大小
VOID * pBaseFunctionAddress; //函数地址
CHAR * szBaseFunctionName; //函数名
} GLOBAL_FUNCTION_TABLE, *PGLOBAL_FUNCTION_TABLE;
typedef GLOBAL_FUNCTION_TABLE USERFUNINFO;
//本地函数调用参数传递协议
typedef struct _GLOBAL_FUNCTION_PARAM {
USERFUNINFO UserFunInfo; //自定义函数信息
LONG_PTR lReturnValue; //函数返回值
VOID * pFunctionParam; //自定义函数参数结构协议
//......<参数顺序从左至右>
} GLOBAL_FUNCTION_PARAM, *PGLOBAL_FUNCTION_PARAM;
#pragma pack()
//数据初始化
/****************************************************************************************************************************************/
//本地函数功能全局数据初始化
BOOL __cdecl InitLocalProcedureCall(void);
//释放本地函数功能全局数据
BOOL __cdecl UnitLocalProcedureCall(void);
/****************************************************************************************************************************************/
//内存管理功能
/****************************************************************************************************************************************/
//关闭进程句柄
void __cdecl CloseProcessHandle(HANDLE * hProcess);
//释放指定进程虚拟内存
void __cdecl FreeClientVirtualMemory(void ** lpVirtualMemory);
void __cdecl FreeServerVirtualMemory(HANDLE * hProcess, void ** lpVirtualMemory, unsigned int * lpLength);
//分配指定进程虚拟内存
HANDLE __cdecl AllocationVirtualMemory(DWORD dwPid, void ** lpVirtualMemory, unsigned int * lpLength);
//写如指定进程虚拟内存
BOOL __cdecl WriteVirtualMemory(HANDLE hProcess, void * lpVirtualMemory, void * lpMemoryContent, unsigned int * lpLength);
/****************************************************************************************************************************************/
//内存映射功能
/****************************************************************************************************************************************/
//释放指定映射内存
void __cdecl MapFreeVirtualMemory(HANDLE * hMapObject, void ** lpVirtualMemory, unsigned int vmLength);
//打开已创建的映射内存,必须调用MapFreeVirtualMemory释放打开的映射内存
HANDLE __cdecl MapOpenVirtualMemory(const char * szPathName, unsigned int wsLength, void ** lpVirtualMemory, unsigned int * lpVmLength);
//创建一块固定大小的映射内存,必须调用MapFreeVirtualMemory释放创建的映射内存
HANDLE __cdecl MapCreateVirtualMemory(const char * szPathName, unsigned int wsLength, void ** lpVirtualMemory, unsigned int * lpVmLength);
/****************************************************************************************************************************************/
//函数同步临界区
/****************************************************************************************************************************************/
//同步锁定
#define LOCK ::RtlEnterCriticalSection(&g_CriticalSection)
//恢复释放
#define ULOCK ::RtlLeaveCriticalSection(&g_CriticalSection); \
::ExitThread(GetQuitThreadCode())
//设置访问控制
#define OnAccessControl(T) InterlockedIncrement(&(T)->uIsAccessOpera)
//解除访问控制
#define OffAccessControl(T) InterlockedDecrement(&(T)->uIsAccessOpera)
//开始操作
#define ENT(T) OnAccessControl(T)
//线程退出
#define RET ::ExitThread(GetQuitThreadCode())
/****************************************************************************************************************************************/
#define MAX_OBJECT_NAME_SIZE (64U)
//线程管理
/****************************************************************************************************************************************/
//获取线程退出代码
DWORD __cdecl GetQuitThreadCode(void);
//创建临时函数调用线程
BOOL __cdecl CreateProCallThread(void * pBaseFunAddr, DWORD dwPid);
/****************************************************************************************************************************************/
//充填自定义函数数据
/****************************************************************************************************************************************/
//设置函数数据
#define SETFUNCTIONTABLE(I,S,N,F) \
g_FunctionObjectTable[(I)].dwBaseParamSize = (S); \
g_FunctionObjectTable[(I)].szBaseFunctionName = (N); \
g_FunctionObjectTable[(I)].hMapObject = MapCreateVirtualMemory( (const char *)g_FunctionObjectTable[(I)].szBaseFunctionName, \
strnlen(g_FunctionObjectTable[(I)].szBaseFunctionName, MAX_OBJECT_NAME_SIZE), \
&g_FunctionObjectTable[(I)].pBaseParamData, \
(unsigned int *)&g_FunctionObjectTable[(I)].dwBaseParamSize ); \
g_FunctionObjectTable[(I)].pBaseFunctionAddress = (F); \
g_FunctionObjectTable[(I)].dwServerId = ::GetCurrentProcessId(); \
memcpy(g_FunctionObjectTable[(I)].pBaseParamData, &g_FunctionObjectTable[(I)], sizeof(USERFUNINFO))
//释放函数数据
#define FREEFUNCTIONTABLE(I) \
MapFreeVirtualMemory( &g_FunctionObjectTable[(I)].hMapObject, \
&g_FunctionObjectTable[(I)].pBaseParamData, \
g_FunctionObjectTable[(I)].dwBaseParamSize )
/****************************************************************************************************************************************/
#define MAX_FUNCTION_COUNT (256U)
//功能全局数据
/****************************************************************************************************************************************/
//临界区数据
extern CRITICAL_SECTION g_CriticalSection;
//函数数据表
extern GLOBAL_FUNCTION_TABLE g_FunctionObjectTable[MAX_FUNCTION_COUNT];
/****************************************************************************************************************************************/
/**********************************AlLocalProcedureCall.cpp**********************************/
// AlLocalProcedureCall.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "AlLocalProcedureCall.h"
#include "TestLpcFunction.h"
CRITICAL_SECTION g_CriticalSection = { NULL };
GLOBAL_FUNCTION_TABLE g_FunctionObjectTable[MAX_FUNCTION_COUNT] = { NULL };
HANDLE __cdecl AllocationVirtualMemory(DWORD dwPid, void ** lpVirtualMemory, unsigned int * lpLength)
{
HANDLE hProcess;
NTSTATUS lNtStatus;
CLIENT_ID ClientProcessId;
OBJECT_ATTRIBUTES ObjectProAttrib;
if (NULL == lpLength || TRUE == ::IsBadWritePtr(lpVirtualMemory, sizeof(void **)))
{
return NULL;
}
ClientProcessId.UniqueThread = 0U;
ClientProcessId.UniqueProcess = dwPid;
InitializeObjectAttributes(&ObjectProAttrib, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
lNtStatus = ::NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &ObjectProAttrib, &ClientProcessId);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
lNtStatus = ::NtAllocateVirtualMemory(hProcess, lpVirtualMemory, 0U, (PULONG)lpLength, MEM_COMMIT, PAGE_READWRITE);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
return hProcess;
}
void __cdecl CloseProcessHandle(HANDLE * hProcess)
{
if (hProcess != NULL)
{
::NtClose(*hProcess);
*hProcess = NULL;
}
}
void __cdecl FreeClientVirtualMemory(void ** lpVirtualMemory)
{
ULONG RegionSize = sizeof(ULONG);
if (::IsBadWritePtr(lpVirtualMemory, RegionSize) != TRUE)
{
::NtFreeVirtualMemory(::GetCurrentProcess(), lpVirtualMemory, (PULONG)&RegionSize, MEM_DECOMMIT);
*lpVirtualMemory = NULL;
}
}
void __cdecl FreeServerVirtualMemory(HANDLE * hProcess, void ** lpVirtualMemory, unsigned int * lpLength)
{
if (lpLength != NULL && hProcess != NULL && ::IsBadWritePtr(*lpVirtualMemory, *lpLength) != TRUE)
{
::NtFreeVirtualMemory(hProcess, lpVirtualMemory, (PULONG)lpLength, MEM_DECOMMIT);
lpVirtualMemory = NULL;
::NtClose(hProcess);
*hProcess = NULL;
*lpLength = 0U;
}
}
BOOL __cdecl WriteVirtualMemory(HANDLE hProcess, void * lpVirtualMemory, void * lpMemoryContent, unsigned int * lpLength)
{
NTSTATUS lNtStatus;
if (lpLength != NULL && &hProcess != NULL &&
lpVirtualMemory != NULL && ::IsBadReadPtr(lpMemoryContent, *lpLength) != TRUE)
{
lNtStatus = ::NtWriteVirtualMemory(hProcess, lpVirtualMemory, lpMemoryContent, *lpLength, (PULONG)&lpLength);
if (NT_SUCCESS(lNtStatus))
{
return TRUE;
}
}
return FALSE;
}
HANDLE __cdecl MapCreateVirtualMemory(const char * szPathName, unsigned int wsLength, void ** lpVirtualMemory, unsigned int * lpVmLength)
{
BOOL bIs64System;
HANDLE hMapSection;
NTSTATUS lNtStatus;
ANSI_STRING szObjectName;
LARGE_INTEGER mLageInteger;
UNICODE_STRING wsObjectName;
OBJECT_ATTRIBUTES mObjectAttris;
WCHAR BaseObjectName[MAX_PATH] = { NULL };
if (TRUE == ::IsBadReadPtr(szPathName, wsLength) ||
TRUE == ::IsBadWritePtr(&lpVirtualMemory, sizeof(void **)) || NULL == lpVmLength)
{
return NULL;
}
szObjectName.Length = wsLength;
szObjectName.MaximumLength = (wsLength + 1U);
szObjectName.Buffer = const_cast<PCHAR>(szPathName);
lNtStatus = ::RtlAnsiStringToUnicodeString(&wsObjectName, &szObjectName, TRUE);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
if (::IsWow64Process(::GetCurrentProcess(), &bIs64System) != TRUE)
{
::RtlFreeUnicodeString(&wsObjectName);
return NULL;
}
if (TRUE == bIs64System)
{
wcsncpy(BaseObjectName, L"\\Sessions\\?\\BaseNamedObjects", MAX_PATH);
for (register unsigned int i = 0U; i < MAX_PATH; ++i)
{
const unsigned short uNumber = 0x30 + i;
BaseObjectName[10] = uNumber;
::RtlFormatObjectAttributes(&mObjectAttris, NULL, &wsObjectName, BaseObjectName);
if (NULL != mObjectAttris.hRootDirectory)
{
break;
}
}
}
else
{
wcsncpy(BaseObjectName, L"\\BaseNamedObjects", MAX_PATH);
::RtlFormatObjectAttributes(&mObjectAttris, NULL, &wsObjectName, BaseObjectName);
}
if (NULL == mObjectAttris.hRootDirectory)
{
::RtlFreeUnicodeString(&wsObjectName);
return NULL;
}
mLageInteger.HighPart = 0U;
mLageInteger.LowPart = *lpVmLength;
//lNtStatus = ::NtCreateSection(&hMapSection, SECTION_MAP_READ | SECTION_MAP_WRITE,
// &mObjectAttris, &mLageInteger, PAGE_READWRITE, SEC_COMMIT, NULL);
lNtStatus = ::NtCreateSection(&hMapSection, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY
| SECTION_MAP_WRITE | SECTION_MAP_READ, &mObjectAttris, &mLageInteger, PAGE_READWRITE, SEC_COMMIT, NULL);
::RtlFreeUnicodeString(&wsObjectName);
::NtClose(mObjectAttris.hRootDirectory);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
lNtStatus = ::NtMapViewOfSection(hMapSection, ::GetCurrentProcess(), lpVirtualMemory, 0U, /**vmLength*/0U,
NULL, (PULONG)lpVmLength, ViewShare, /*MEM_LARGE_PAGES*/0U, PAGE_READWRITE);
if (NT_SUCCESS(lNtStatus))
{
//::NtClose(hMapSection);
::NtFlushInstructionCache(::GetCurrentProcess(), lpVirtualMemory, *lpVmLength);
return hMapSection;
}
return NULL;
}
void __cdecl MapFreeVirtualMemory(HANDLE * hMapObject, void ** lpVirtualMemory, unsigned int vmLength)
{
if (hMapObject != NULL && TRUE != ::IsBadWritePtr(*lpVirtualMemory, vmLength))
{
::NtUnmapViewOfSection(::GetCurrentProcess(), *lpVirtualMemory);
*lpVirtualMemory = NULL;
::NtClose(*hMapObject);
*hMapObject = NULL;
}
}
HANDLE __cdecl MapOpenVirtualMemory(const char * szPathName, unsigned int wsLength, void ** lpVirtualMemory, unsigned int * lpVmLength)
{
BOOL bIs64System;
HANDLE hMapObject;
NTSTATUS lNtStatus;
ANSI_STRING szObjectName;
UNICODE_STRING wsObjectName;
OBJECT_ATTRIBUTES mObjectAttris;
WCHAR BaseObjectName[MAX_PATH] = { NULL };
if (TRUE == ::IsBadReadPtr(szPathName, wsLength) || NULL == lpVmLength)
{
return NULL;
}
szObjectName.Length = wsLength;
szObjectName.MaximumLength = (wsLength + 1U);
szObjectName.Buffer = const_cast<PCHAR>(szPathName);
lNtStatus = ::RtlAnsiStringToUnicodeString(&wsObjectName, &szObjectName, TRUE);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
if (::IsWow64Process(::GetCurrentProcess(), &bIs64System) != TRUE)
{
::RtlFreeUnicodeString(&wsObjectName);
return NULL;
}
if (TRUE == bIs64System)
{
wcsncpy(BaseObjectName, L"\\Sessions\\?\\BaseNamedObjects", MAX_PATH);
for (register unsigned int i = 0U; i < MAX_PATH; ++i)
{
const unsigned int uNumber = 0x30 + i;
BaseObjectName[10] = uNumber;
::RtlFormatObjectAttributes(&mObjectAttris, NULL, &wsObjectName, BaseObjectName);
if (NULL != mObjectAttris.hRootDirectory)
break;
}
}
else
{
wcsncpy(BaseObjectName, L"\\BaseNamedObjects", MAX_PATH);
::RtlFormatObjectAttributes(&mObjectAttris, NULL, &wsObjectName, BaseObjectName);
}
if (NULL == mObjectAttris.hRootDirectory)
{
::RtlFreeUnicodeString(&wsObjectName);
return NULL;
}
lNtStatus = ::NtOpenSection(&hMapObject, FILE_MAP_ALL_ACCESS, &mObjectAttris);
::NtClose(mObjectAttris.hRootDirectory);
if (!(NT_SUCCESS(lNtStatus)))
{
return NULL;
}
lNtStatus = ::NtMapViewOfSection(hMapObject, ::GetCurrentProcess(), lpVirtualMemory, 0U, /**vmLength*/0U,
NULL, (PULONG)lpVmLength, ViewShare, /*MEM_LARGE_PAGES*/0U, PAGE_READWRITE);
if (NT_SUCCESS(lNtStatus))
{
::NtFlushInstructionCache(::GetCurrentProcess(), lpVirtualMemory, *lpVmLength);
return hMapObject;
}
return NULL;
}
DWORD __cdecl GetQuitThreadCode(void)
{
DWORD dwExitThreadCode;
if (FALSE == ::GetExitCodeThread(::GetCurrentThread(), &dwExitThreadCode))
{
return 0U;
}
return dwExitThreadCode;
}
#define MAX_STACK_SIZE (256U)
BOOL __cdecl CreateProCallThread(void * pBaseFunAddr, DWORD dwPid)
{
NTSTATUS ntStatus;
HANDLE hCallThread;
HANDLE hCallProcess;
CLIENT_ID ClientThreadId;
CLIENT_ID ClientProcessId;
INITIAL_TEB InitialThreadStack;
OBJECT_ATTRIBUTES ObjectProAttrib;
OBJECT_ATTRIBUTES ObjectTedAttrib;
CONTEXT ThreadContext = { CONTEXT_FULL };
if (NULL == pBaseFunAddr)
{
return FALSE;
}
ClientProcessId.UniqueThread = 0U;
ClientProcessId.UniqueProcess = dwPid;
InitializeObjectAttributes(&ObjectProAttrib, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = ::NtOpenProcess(&hCallProcess, PROCESS_ALL_ACCESS, &ObjectProAttrib, &ClientProcessId);
if (!(NT_SUCCESS(ntStatus)))
{
return FALSE;
}
ntStatus = ::RtlCreateStack(hCallProcess, MAX_STACK_SIZE, (MAX_STACK_SIZE * 2U), &InitialThreadStack);
if (!(NT_SUCCESS(ntStatus)))
{
::NtClose(hCallProcess);
return FALSE;
}
InitializeObjectAttributes(&ObjectTedAttrib, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
BaseInitializeContext(&ThreadContext, NULL, pBaseFunAddr, InitialThreadStack.StackBase, EipStartParam);
ntStatus = ::NtCreateThread(&hCallThread, THREAD_ALL_ACCESS, &ObjectTedAttrib, hCallProcess,
&ClientThreadId, &ThreadContext, &InitialThreadStack, FALSE);
::NtClose(ObjectTedAttrib.hRootDirectory);
if (!(NT_SUCCESS(ntStatus)))
{
::RtlFreeThreadStack(hCallProcess, &InitialThreadStack);
::NtClose(hCallProcess);
return FALSE;
}
ntStatus = ::NtWaitForSingleObject(hCallThread, FALSE, NULL);
if (NT_SUCCESS(ntStatus))
{
::RtlFreeThreadStack(hCallProcess, &InitialThreadStack);
::NtClose(hCallProcess);
::NtClose(hCallThread);
}
return TRUE;
}
BOOL __cdecl InitLocalProcedureCall(void)
{
NTSTATUS ntStatus;
ntStatus = ::RtlInitializeCriticalSection(&g_CriticalSection);
if (!(NT_SUCCESS(ntStatus)))
{
return FALSE;
}
//需要初始化的自定义函数资源
SETFUNCTIONTABLE(SUB, sizeof(sub_data), "sub", lpc_sub);
SETFUNCTIONTABLE(ADD, sizeof(add_data), "add", lpc_add);
return TRUE;
}
BOOL __cdecl UnitLocalProcedureCall(void)
{
NTSTATUS ntStatus;
//需要释放的自定义函数资源
FREEFUNCTIONTABLE(SUB);
FREEFUNCTIONTABLE(ADD);
ntStatus = ::RtlDeleteCriticalSection(&g_CriticalSection);
if (!(NT_SUCCESS(ntStatus)))
{
return FALSE;
}
return TRUE;
}
/**********************************dllmain.cpp**********************************/
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "AlLocalProcedureCall.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
::DisableThreadLibraryCalls(hModule);
return InitLocalProcedureCall();
case DLL_THREAD_ATTACH:
::DisableThreadLibraryCalls(hModule);
return InitLocalProcedureCall();
case DLL_THREAD_DETACH:
return UnitLocalProcedureCall();
case DLL_PROCESS_DETACH:
return UnitLocalProcedureCall();
}
return TRUE;
}
/**********************************TestLpcFunction.h**********************************/
#pragma once
#pragma pack(1)
typedef struct _OPERATOR_DATA {
int x;
int y;
int z;
} OPERATOR_DATA, *POPERATOR_DATA;
//参考:
//本地函数调用参数传递协议
//typedef struct _GLOBAL_FUNCTION_PARAM {
// USERFUNINFO UserFunInfo; //自定义函数信息
// LONG_PTR lReturnValue; //函数返回值
// VOID * pFunctionParam; //自定义函数参数结构协议
// //......<参数顺序从左至右>
//} GLOBAL_FUNCTION_PARAM, *PGLOBAL_FUNCTION_PARAM;
struct add_data {
USERFUNINFO UserFunInfo; //自定义函数信息
int r; //out r 返回值
int x; //in x 参数1
int y; //in y 参数2
OPERATOR_DATA od; //out od 参数3
};
struct sub_data {
USERFUNINFO UserFunInfo; //自定义函数信息
POPERATOR_DATA r; //out 函数返回值
int x; //in 传入参数x
int y; //in 传入参数y
};
#pragma pack()
#define SUB (0)
void __cdecl lpc_sub(void);
#define ADD (1)
void __cdecl lpc_add(void);
/**********************************TestLpcFunction.cpp**********************************/
#include "stdafx.h"
#include "AlLocalProcedureCall.h"
#include "TestLpcFunction.h"
static POPERATOR_DATA sub(unsigned int uPid, int x, int y)
{
HANDLE hMemory;
OPERATOR_DATA od;
POPERATOR_DATA lpOperData = NULL;
unsigned int uSize = sizeof(OPERATOR_DATA);
hMemory = AllocationVirtualMemory(uPid, (void **)&lpOperData, &uSize);
if (NULL == hMemory)
{
return NULL;
}
if (lpOperData != NULL)
{
od.x = x;
od.y = y;
od.z = x - y;
uSize = sizeof(OPERATOR_DATA);
if (WriteVirtualMemory(hMemory, lpOperData, &od, &uSize) == TRUE)
{
CloseProcessHandle(&hMemory);
return lpOperData;
}
}
CloseProcessHandle(&hMemory);
return NULL;
}
void lpc_sub(void)
{
sub_data * lpSubParam = (sub_data *)g_FunctionObjectTable[SUB].pBaseParamData;
if (lpSubParam != NULL)
{
ENT(&lpSubParam->UserFunInfo);
lpSubParam->r = sub(lpSubParam->UserFunInfo.dwClientId, lpSubParam->x, lpSubParam->y);
RET;
}
}
static int add(int x, int y, POPERATOR_DATA od)
{
if (od != NULL)
{
od->x = x;
od->y = y;
od->z = x + y;
return (od->z);
}
return 0;
}
void lpc_add(void)
{
add_data * lpAddData = (add_data *)g_FunctionObjectTable[ADD].pBaseParamData;
if (lpAddData != NULL)
{
ENT(&lpAddData->UserFunInfo);
lpAddData->r = add(lpAddData->x, lpAddData->y, &lpAddData->od);
RET;
}
}
/**********************************TestAlLpc.cpp**********************************/
// TestAlLpc.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "AlLocalProcedureCall.h"
#include "TestLpcFunction.h"
//#include <KtmW32.h>
//#pragma comment(lib,"KtmW32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
//HMODULE hModule = ::LoadLibraryA("AlLocalProcedureCall");
//if (hModule != NULL)
{
sub_data * lpSubData = NULL;
UINT uSubSize = sizeof(sub_data);
HANDLE hLoaclMap = MapOpenVirtualMemory("sub", strlen("sub"), (void **)&lpSubData, &uSubSize);
if (NULL == hLoaclMap)
{
printf("Sub函数信息没有找到!\r\n");
}
else
{
while (lpSubData->UserFunInfo.uIsAccessOpera > 0U)
{
printf("地址空间正被访问!\r\n");
::Sleep(10U);
}
//设置参数数据
lpSubData->x = 1;
lpSubData->y = 2;
lpSubData->UserFunInfo.dwClientId = ::GetCurrentProcessId();
//调用函数
BOOL bCallSub = CreateProCallThread(lpSubData->UserFunInfo.pBaseFunctionAddress, lpSubData->UserFunInfo.dwServerId);
if (TRUE == bCallSub)
{
uSubSize = sizeof(sub_data);
printf("减法函数:参数x = %d 参数y = %d 返回r = %d\r\n", lpSubData->x, lpSubData->y, lpSubData->r->z);
//客服端调用API释放即可
FreeClientVirtualMemory((void **)&lpSubData->r);
}
OffAccessControl(&lpSubData->UserFunInfo);
MapFreeVirtualMemory(&hLoaclMap, (void **)&lpSubData, uSubSize);
add_data * lpAddData = NULL;
UINT uAddSize = sizeof(add_data);
hLoaclMap = MapOpenVirtualMemory("add", strlen("add"), (void **)&lpAddData, &uAddSize);
if (NULL == hLoaclMap)
{
printf("Add函数信息没有找到!\r\n");
}
else
{
while (lpAddData->UserFunInfo.uIsAccessOpera > 0U)
{
printf("地址空间正被访问!\r\n");
::Sleep(10U);
}
//设置参数数据
lpAddData->x = 1;
lpAddData->y = 2;
lpAddData->UserFunInfo.dwClientId = ::GetCurrentProcessId();
//调用函数
bCallSub = CreateProCallThread(lpAddData->UserFunInfo.pBaseFunctionAddress, lpAddData->UserFunInfo.dwServerId);
if (TRUE == bCallSub)
{
printf("加法函数:参数x = %d 参数y = %d 返回r = %d\r\n", lpAddData->od.x, lpAddData->od.y, lpAddData->od.z);
}
OffAccessControl(&lpAddData->UserFunInfo);
MapFreeVirtualMemory(&hLoaclMap, (void **)&lpAddData, uAddSize);
}
}
//::FreeLibrary(hModule);
}
return 0;
}
以上为测试自定义LPC机制框架所有代码,应用了Windows强大的内存映射功能,至于无公开的库文件及函数请咨询MSDN。