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

来源:互联网 发布:cent 7 在线音乐软件 编辑:程序博客网 时间:2024/06/08 11:22

前言:Windows自带的RPC通信在通过LPC处理时有很多不足之处,例如不支持参数传入传出指针是一件很不幸的事情,以下是一个简单自定义LPC框架,暂不支持网络调用;


/**********************************AlLocalProcedureCall.h**********************************/

#pragma once#define PAGE_SIZE (4096U)#pragma pack(1)//本地函数调用数据结构typedef struct _GLOBAL_FUNCTION_TABLE {DWORD dwClientId;  //客服进程IDDWORD dwServerId;  //服务进程IDHANDLE 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 参数1int y; //in y 参数2OPERATOR_DATA od; //out od 参数3};struct sub_data {USERFUNINFO UserFunInfo; //自定义函数信息POPERATOR_DATA r; //out 函数返回值int x; //in 传入参数xint 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。








0 0
原创粉丝点击