简单之LPC跨进程通信(支持指针传参)

前言: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。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值