├── README.md ├── LPC ├── ldasm.c ├── Kernel.c ├── makefile ├── sources ├── ldasm.h ├── CommonDefs.h ├── UserModeDefs.h ├── KernelModeDefs.h ├── LPC.h ├── LPC.vcxproj └── LPC.c ├── LPCTest ├── makefile ├── sources ├── LPCTest.inf ├── x86kernel │ └── LPCTest.inf ├── LPCTest.c └── LPCTest.vcxproj ├── .gitignore ├── DemoClient ├── DemoClient.cpp └── DemoClient.vcxproj ├── DemoServer ├── DemoServer.cpp └── DemoServer.vcxproj ├── DriverComplie.py ├── VersionSelector.sln └── inc ├── utstring.h ├── utarray.h └── utlist.h /README.md: -------------------------------------------------------------------------------- 1 | LPC 2 | === 3 | 4 | windows LPC library -------------------------------------------------------------------------------- /LPC/ldasm.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalon1610/LPC/HEAD/LPC/ldasm.c -------------------------------------------------------------------------------- /LPC/Kernel.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalon1610/LPC/HEAD/LPC/Kernel.c -------------------------------------------------------------------------------- /LPC/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the components of NT 5 | # 6 | !INCLUDE $(NTMAKEENV)/makefile.def 7 | 8 | 9 | -------------------------------------------------------------------------------- /LPCTest/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the components of NT 5 | # 6 | !INCLUDE $(NTMAKEENV)/makefile.def 7 | 8 | 9 | -------------------------------------------------------------------------------- /LPCTest/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=LPCTest 2 | TARGETPATH=../bin 3 | TARGETTYPE=DRIVER 4 | TARGETLIBS=..\lib_r0\i386\lpc.lib 5 | 6 | C_DEFINES=$(C_DEFINES) /D_KERNEL_MODE 7 | !if $(FREEBUILD) 8 | MSC_WARNING_LEVEL=/W1 9 | !else 10 | MSC_WARNING_LEVEL=/W3 11 | !endif 12 | 13 | SOURCES=LPCTest.c -------------------------------------------------------------------------------- /LPC/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=LPC 2 | TARGETPATH=../lib_r0 3 | TARGETTYPE=DRIVER_LIBRARY 4 | 5 | C_DEFINES=$(C_DEFINES) /D_KERNEL_MODE 6 | !if $(FREEBUILD) 7 | MSC_WARNING_LEVEL=/W1 8 | !else 9 | MSC_WARNING_LEVEL=/W3 10 | !endif 11 | 12 | SOURCES=LPC.c \ 13 | Kernel.c \ 14 | ldasm.c 15 | 16 | -------------------------------------------------------------------------------- /LPC/ldasm.h: -------------------------------------------------------------------------------- 1 | #ifndef _LDASM_ 2 | #define _LDASM_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | unsigned long __fastcall SizeOfCode(void *Code, unsigned char **pOpcode); 9 | 10 | unsigned long __fastcall SizeOfProc(void *Proc); 11 | 12 | char __fastcall IsRelativeCmd(unsigned char *pOpcode); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | 11 | # Compiled Static libraries 12 | *.lai 13 | *.la 14 | *.a 15 | 16 | *.log 17 | *.idb 18 | *.pdb 19 | *.lastbuildstate 20 | *.tlog 21 | *.filters 22 | *.user 23 | *.sdf 24 | *.ilk 25 | *.exe 26 | *.lib 27 | *.sys 28 | *.mac 29 | *.xml 30 | *.unsuccessfulbuild 31 | *.suo 32 | *.err 33 | *.wrn 34 | *.dll 35 | *.opensdf 36 | 37 | 38 | -------------------------------------------------------------------------------- /LPCTest/LPCTest.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; LPCTest.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class= 8 | ClassGuid= 9 | Provider= 10 | DriverVer= 11 | CatalogFile= 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" 31 | ClassName="" 32 | DiskName="LPCTest Source Disk" 33 | -------------------------------------------------------------------------------- /LPCTest/x86kernel/LPCTest.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; LPCTest.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class= 8 | ClassGuid= 9 | Provider= 10 | DriverVer=04/11/2013,16.30.55.456 11 | CatalogFile= 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NTx86 25 | 26 | [Standard.NTx86] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" 31 | ClassName="" 32 | DiskName="LPCTest Source Disk" 33 | -------------------------------------------------------------------------------- /DemoClient/DemoClient.cpp: -------------------------------------------------------------------------------- 1 | #include "../LPC/LPC.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #pragma comment(lib,"LPC.lib") 7 | using namespace std; 8 | 9 | void wait() 10 | { 11 | MSG msg; 12 | while (GetMessage(&msg,NULL,0,0)) 13 | { 14 | TranslateMessage(&msg); 15 | DispatchMessage(&msg); 16 | } 17 | } 18 | 19 | #define COMMAND_DOSOMETHING LPC_COMMAND_RESERVE+0x1 20 | int _tmain(int argc, _TCHAR* argv[]) 21 | { 22 | Connect(SERVERNAME_W); 23 | TCHAR msg[LARGE_MESSAGE_SIZE] = {0}; 24 | while(true) 25 | { 26 | wcin >> msg; 27 | //lpcClient.SyncSend(msg); 28 | Control(COMMAND_DOSOMETHING,SYNC,msg); 29 | } 30 | wait(); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /DemoServer/DemoServer.cpp: -------------------------------------------------------------------------------- 1 | // DemoServer.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "../LPC/LPC.h" 5 | #include 6 | #include 7 | 8 | #pragma comment(lib,"LPC.lib") 9 | #define COMMAND_DOSOMETHING LPC_COMMAND_RESERVE+0x1 10 | void wait() 11 | { 12 | MSG msg; 13 | while (GetMessage(&msg,NULL,0,0)) 14 | { 15 | TranslateMessage(&msg); 16 | DispatchMessage(&msg); 17 | } 18 | } 19 | 20 | void talk(LPVOID param) 21 | { 22 | TCHAR *msg = (TCHAR *)param; 23 | MessageBox(NULL,msg,NULL,NULL); 24 | } 25 | 26 | int _tmain(int argc, _TCHAR* argv[]) 27 | { 28 | InsertCallBack(COMMAND_DOSOMETHING,talk); 29 | runServer(SERVERNAME_W); 30 | wait(); 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /LPCTest/LPCTest.c: -------------------------------------------------------------------------------- 1 | #include "ntifs.h" 2 | #include "..\LPC\LPC.h" 3 | 4 | 5 | NTSTATUS DefaultDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp) 6 | { 7 | NTSTATUS status = STATUS_SUCCESS; 8 | UNREFERENCED_PARAMETER(DeviceObject); 9 | Irp->IoStatus.Status = status; 10 | Irp->IoStatus.Information = 0; 11 | IoCompleteRequest(Irp,IO_NO_INCREMENT); 12 | return status; 13 | } 14 | 15 | #define COMMAND_DOSOMETHING LPC_COMMAND_RESERVE+0x1 16 | 17 | void talk(PVOID param) 18 | { 19 | TCHAR *msg; 20 | msg = (TCHAR *)param; 21 | KdPrint(("callback message:%ws\n",msg)); 22 | PsTerminateSystemThread(STATUS_SUCCESS); 23 | } 24 | 25 | 26 | void DriverUnload(PDRIVER_OBJECT DriverObject) 27 | { 28 | UNREFERENCED_PARAMETER(DriverObject); 29 | StopServer((TCHAR *)SERVERNAME_W); 30 | KdPrint(("LPCTest Unloaded!\n")); 31 | } 32 | 33 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegPath) 34 | { 35 | ULONG i; 36 | UNREFERENCED_PARAMETER(DriverObject); 37 | UNREFERENCED_PARAMETER(RegPath); 38 | 39 | for (i = 0;i < IRP_MJ_MAXIMUM_FUNCTION;i++) 40 | DriverObject->MajorFunction[i] = DefaultDispatch; 41 | DriverObject->DriverUnload = DriverUnload; 42 | 43 | runServer((TCHAR *)SERVERNAME_W); 44 | InsertCallBack(COMMAND_DOSOMETHING,talk); 45 | 46 | return STATUS_SUCCESS; 47 | } -------------------------------------------------------------------------------- /DriverComplie.py: -------------------------------------------------------------------------------- 1 | from subprocess import * 2 | import re 3 | from msvcrt import getch 4 | 5 | class InteractiveCommand: 6 | def __init__(self,process,prompt): 7 | self.process = process 8 | self.prompt = prompt 9 | self.output = "" 10 | self.wait_for_prompt() 11 | 12 | def wait_for_prompt(self): 13 | while not self.prompt.search(self.output): 14 | c = self.process.stdout.read(1) 15 | if c == "": 16 | break 17 | self.output += c 18 | 19 | # clear the output buffer and return its content 20 | tmp = self.output 21 | self.output = "" 22 | return tmp 23 | 24 | def command(self,command): 25 | print command 26 | self.process.stdin.write(command + "\n") 27 | return self.wait_for_prompt() 28 | 29 | # ######################################################## 30 | # setup driver environment variable here 31 | 32 | # Winddk path 33 | winddk = 'D:\\WinDDK\\7600.16385.1\\' 34 | 35 | # [free=fre=f|checked=chk=CHK=c] [x86=IA32=I386|x64=x32-64|64=IA64] [WIN7|Wlh|WXP|WNET] 36 | environment = 'chk' 37 | platform = 'x86' 38 | target_os = 'WIN7' 39 | 40 | # build path,place them in order 41 | build_path = ['E:\\Projects\\LPC\\LPC','E:\\Projects\\LPC\\LPCTest'] 42 | # ######################################################## 43 | 44 | set_env = ['%sbin\\setenv.bat' % winddk,winddk,environment,platform,target_os,'no_oacr'] 45 | command = ['cmd.exe','/k'] + set_env 46 | print command 47 | 48 | p = Popen(command,stdin=PIPE,stdout=PIPE) 49 | prompt = re.compile(r"^[EeCcDdFfGg]:\\.*>",re.M) 50 | cmd = InteractiveCommand(p,prompt) 51 | 52 | for path in build_path: 53 | cmd.command("cd /d %s" % path) 54 | cmd.command("build") 55 | 56 | cmd.command("exit") 57 | getch() 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /LPC/CommonDefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _KERNEL_MODE 4 | #include "UserModeDefs.h" 5 | #else 6 | //#define RTL_USE_AVL_TABLES 0 7 | #include "ntifs.h" 8 | #include "Ntstrsafe.h" 9 | #include "ntimage.h" 10 | //#include "KernelModeDefs.h" 11 | #pragma comment(lib,"Ntstrsafe.lib") 12 | #define SEC_IMAGE 0x1000000 13 | #endif 14 | /* 15 | this header file defines all thing that could be used by ring0 and ring3 16 | for example, simple convention of connection , user-defined struct , macros , and so on 17 | */ 18 | 19 | // 20 | // Define header for Port Message 21 | // 22 | typedef struct _PORT_MESSAGE 23 | { 24 | union 25 | { 26 | struct 27 | { 28 | USHORT DataLength; // Length of data following the header (bytes) 29 | USHORT TotalLength; // Length of data + sizeof(PORT_MESSAGE) 30 | } s1; 31 | ULONG Length; 32 | } u1; 33 | 34 | union 35 | { 36 | struct 37 | { 38 | USHORT Type; 39 | USHORT DataInfoOffset; 40 | } s2; 41 | ULONG ZeroInit; 42 | } u2; 43 | 44 | union 45 | { 46 | CLIENT_ID ClientId; 47 | double DoNotUseThisField; // Force quadword alignment 48 | }; 49 | 50 | SIZE_T MessageId; // Identifier of the particular message instance 51 | 52 | union 53 | { 54 | ULONG_PTR ClientViewSize; // Size of section created by the sender (in bytes) 55 | ULONG CallbackId; // 56 | }; 57 | 58 | } PORT_MESSAGE, *PPORT_MESSAGE; 59 | // 60 | // Define structure for initializing shared memory on the caller's side of the port 61 | // 62 | 63 | typedef struct _PORT_VIEW { 64 | 65 | SIZE_T Length; // Size of this structure 66 | HANDLE SectionHandle; // Handle to section object with 67 | // SECTION_MAP_WRITE and SECTION_MAP_READ 68 | PVOID SectionOffset; // The offset in the section to map a view for 69 | 70 | // the port data area. The offset must be aligned 71 | // with the allocation granularity of the system. 72 | SIZE_T ViewSize; // The size of the view (in bytes) 73 | PVOID ViewBase; // The base address of the view in the creator 74 | // 75 | PVOID ViewRemoteBase; // The base address of the view in the process 76 | // connected to the port. 77 | } PORT_VIEW, *PPORT_VIEW; 78 | 79 | // 80 | // Define structure for shared memory coming from remote side of the port 81 | // 82 | 83 | typedef struct _REMOTE_PORT_VIEW { 84 | 85 | SIZE_T Length; // Size of this structure 86 | SIZE_T ViewSize; // The size of the view (bytes) 87 | PVOID ViewBase; // Base address of the view 88 | 89 | } REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW; 90 | 91 | #ifdef _KERNEL_MODE 92 | #include "KernelModeDefs.h" 93 | #endif // _KERNEL_MODE 94 | 95 | -------------------------------------------------------------------------------- /LPCTest/LPCTest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | x86 kernel 6 | Win32 7 | 8 | 9 | x86 kernel 10 | x64 11 | 12 | 13 | 14 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801} 15 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 16 | v4.5 17 | 11.0 18 | Win8 Debug 19 | Win32 20 | 21 | 22 | LPCTest 23 | $(VCTargetsPath11) 24 | 25 | 26 | WindowsKernelModeDriver8.0 27 | Driver 28 | WDM 29 | 30 | 31 | 32 | Windows8 33 | false 34 | 35 | 36 | Windows8 37 | false 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ..\bin\$(ConfigurationName)\ 48 | d:\WinDDK\7600.16385.1\inc\wdf;d:\WinDDK\7600.16385.1\inc\mfc42;d:\WinDDK\7600.16385.1\inc\ddk;d:\WinDDK\7600.16385.1\inc\crt;d:\WinDDK\7600.16385.1\inc\atl71;d:\WinDDK\7600.16385.1\inc\api;$(IncludePath) 49 | 50 | 51 | DbgengKernelDebugger 52 | 53 | 54 | 55 | ..\lib\x86kernel\lpc.lib%(AdditionalDependencies) 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /LPC/UserModeDefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define FORCEINLINE __forceinline 8 | #define VOID void 9 | #define CONST const 10 | #define NTSTATUS LONG 11 | #define NTAPI __stdcall 12 | 13 | #define IN 14 | #define OUT 15 | 16 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 17 | 18 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 19 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 20 | (p)->RootDirectory = r; \ 21 | (p)->Attributes = a; \ 22 | (p)->ObjectName = n; \ 23 | (p)->SecurityDescriptor = s; \ 24 | (p)->SecurityQualityOfService = NULL; \ 25 | } 26 | 27 | typedef struct _UNICODE_STRING { 28 | USHORT Length; 29 | USHORT MaximumLength; 30 | PWSTR Buffer; 31 | } UNICODE_STRING, *PUNICODE_STRING; 32 | 33 | typedef struct _OBJECT_ATTRIBUTES { 34 | ULONG Length; 35 | HANDLE RootDirectory; 36 | PUNICODE_STRING ObjectName; 37 | ULONG Attributes; 38 | PVOID SecurityDescriptor; 39 | PVOID SecurityQualityOfService; 40 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 41 | typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; 42 | 43 | typedef void (NTAPI* _InitUnicodeString)( 44 | IN OUT PUNICODE_STRING DestinationString, 45 | IN PCWSTR SourceString 46 | ); 47 | 48 | 49 | typedef struct _CLIENT_ID { 50 | HANDLE UniqueProcess; 51 | HANDLE UniqueThread; 52 | } CLIENT_ID,*PCLIENT_ID; 53 | 54 | 55 | 56 | #define InitializeListHead32(ListHead) (\ 57 | (ListHead)->Flink = (ListHead)->Blink = PtrToUlong((ListHead))) 58 | 59 | #define RTL_STATIC_LIST_HEAD(x) LIST_ENTRY x = { &x, &x } 60 | 61 | FORCEINLINE 62 | VOID 63 | InitializeListHead( 64 | _Out_ PLIST_ENTRY ListHead 65 | ) 66 | 67 | { 68 | 69 | ListHead->Flink = ListHead->Blink = ListHead; 70 | return; 71 | } 72 | 73 | _Must_inspect_result_ 74 | BOOLEAN 75 | FORCEINLINE 76 | IsListEmpty( 77 | _In_ const LIST_ENTRY * ListHead 78 | ) 79 | 80 | { 81 | 82 | return (BOOLEAN)(ListHead->Flink == ListHead); 83 | } 84 | 85 | FORCEINLINE 86 | BOOLEAN 87 | RemoveEntryListUnsafe( 88 | _In_ PLIST_ENTRY Entry 89 | ) 90 | 91 | { 92 | 93 | PLIST_ENTRY Blink; 94 | PLIST_ENTRY Flink; 95 | 96 | Flink = Entry->Flink; 97 | Blink = Entry->Blink; 98 | Blink->Flink = Flink; 99 | Flink->Blink = Blink; 100 | return (BOOLEAN)(Flink == Blink); 101 | } 102 | 103 | 104 | FORCEINLINE 105 | BOOLEAN 106 | RemoveEntryList( 107 | _In_ PLIST_ENTRY Entry 108 | ) 109 | 110 | { 111 | 112 | PLIST_ENTRY Blink; 113 | PLIST_ENTRY Flink; 114 | 115 | Flink = Entry->Flink; 116 | Blink = Entry->Blink; 117 | Blink->Flink = Flink; 118 | Flink->Blink = Blink; 119 | return (BOOLEAN)(Flink == Blink); 120 | } 121 | 122 | FORCEINLINE 123 | PLIST_ENTRY 124 | RemoveHeadList( 125 | _Inout_ PLIST_ENTRY ListHead 126 | ) 127 | 128 | { 129 | 130 | PLIST_ENTRY Flink; 131 | PLIST_ENTRY Entry; 132 | 133 | Entry = ListHead->Flink; 134 | Flink = Entry->Flink; 135 | ListHead->Flink = Flink; 136 | Flink->Blink = ListHead; 137 | return Entry; 138 | } 139 | 140 | 141 | 142 | FORCEINLINE 143 | PLIST_ENTRY 144 | RemoveTailList( 145 | _Inout_ PLIST_ENTRY ListHead 146 | ) 147 | 148 | { 149 | 150 | PLIST_ENTRY Blink; 151 | PLIST_ENTRY Entry; 152 | 153 | Entry = ListHead->Blink; 154 | Blink = Entry->Blink; 155 | ListHead->Blink = Blink; 156 | Blink->Flink = ListHead; 157 | return Entry; 158 | } 159 | 160 | 161 | FORCEINLINE 162 | VOID 163 | InsertTailList( 164 | _Inout_ PLIST_ENTRY ListHead, 165 | _Inout_ PLIST_ENTRY Entry 166 | ) 167 | { 168 | 169 | PLIST_ENTRY Blink; 170 | 171 | Blink = ListHead->Blink; 172 | Entry->Flink = ListHead; 173 | Entry->Blink = Blink; 174 | Blink->Flink = Entry; 175 | ListHead->Blink = Entry; 176 | return; 177 | } 178 | 179 | 180 | FORCEINLINE 181 | VOID 182 | InsertHeadList( 183 | _Inout_ PLIST_ENTRY ListHead, 184 | _Inout_ PLIST_ENTRY Entry 185 | ) 186 | { 187 | 188 | PLIST_ENTRY Flink; 189 | 190 | Flink = ListHead->Flink; 191 | Entry->Flink = Flink; 192 | Entry->Blink = ListHead; 193 | Flink->Blink = Entry; 194 | ListHead->Flink = Entry; 195 | return; 196 | } 197 | 198 | FORCEINLINE 199 | VOID 200 | AppendTailList( 201 | _Inout_ PLIST_ENTRY ListHead, 202 | _Inout_ PLIST_ENTRY ListToAppend 203 | ) 204 | { 205 | 206 | PLIST_ENTRY ListEnd = ListHead->Blink; 207 | 208 | ListHead->Blink->Flink = ListToAppend; 209 | ListHead->Blink = ListToAppend->Blink; 210 | ListToAppend->Blink->Flink = ListHead; 211 | ListToAppend->Blink = ListEnd; 212 | return; 213 | } 214 | 215 | typedef std::map MAP; 216 | 217 | -------------------------------------------------------------------------------- /LPC/KernelModeDefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CommonDefs.h" 3 | 4 | 5 | typedef BOOLEAN BOOL; 6 | typedef unsigned short WORD; 7 | typedef unsigned char BYTE; 8 | typedef DWORD * PDWORD; 9 | #define _Out_ 10 | #define _In_ 11 | #define _In_opt_ 12 | 13 | typedef enum WIN_VER_DETAIL{ 14 | WINDOWS_VERSION_NONE, 15 | WINDOWS_VERSION_2K, 16 | WINDOWS_VERSION_XP, 17 | WINDOWS_VERSION_2K3, 18 | WINDOWS_VERSION_2K3_SP1_SP2, 19 | WINDOWS_VERSION_VISTA_2008, 20 | WINDOWS_VERSION_7_7600_UP, 21 | WINDOWS_VERSION_7_7000 22 | } WIN_VER_DETAIL; 23 | 24 | WIN_VER_DETAIL WinVersion; 25 | 26 | typedef NTSTATUS (*PSPTERMINATETHREADBYPOINTER_K)(PETHREAD,NTSTATUS,BOOLEAN); 27 | PSPTERMINATETHREADBYPOINTER_K PspTerminateThreadByPointer_K; 28 | typedef NTSTATUS (*PSPTERMINATETHREADBYPOINTER_XP)(PETHREAD,NTSTATUS); 29 | PSPTERMINATETHREADBYPOINTER_XP PspTerminateThreadByPointer_XP; 30 | 31 | ULONG ThreadProc,ThreadListHead,ActiveProcessLinksOffset,UniqueProcessIdOffset,processpid; 32 | 33 | typedef enum _KAPC_ENVIRONMENT 34 | { 35 | OriginalApcEnvironment, 36 | AttachedApcEnvironment, 37 | CurrentApcEnvironment, 38 | InsertApcEnvironment 39 | } KAPC_ENVIRONMENT; 40 | 41 | NTKERNELAPI 42 | VOID 43 | KeInitializeApc(PKAPC Apc, 44 | PETHREAD Thread, 45 | KAPC_ENVIRONMENT Environment, 46 | PKKERNEL_ROUTINE KernelRoutine, 47 | PKRUNDOWN_ROUTINE RundownRoutine, 48 | PKNORMAL_ROUTINE NormalRoutine, 49 | KPROCESSOR_MODE ProcessorMode, 50 | PVOID NormelContext); 51 | 52 | NTKERNELAPI 53 | BOOLEAN 54 | KeInsertQueueApc(PKAPC Apc, 55 | PVOID SystemArgument1, 56 | PVOID SystemArgument2, 57 | KPRIORITY Increment); 58 | 59 | #define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL 60 | 61 | #pragma pack(push,1) 62 | typedef enum VALIDITY_CHECK_STATUS 63 | { 64 | VCS_INVALID, 65 | VCS_VALID, 66 | VCS_TRANSITION, 67 | VCS_PAGEDOUT, 68 | VCS_DEMANDZERO, 69 | VCS_PROTOTYPE 70 | } VALIDITY_CHECK_STATUS; 71 | 72 | #define PAE_ON (1<<5) 73 | 74 | typedef struct _MMPTE_SOFTWARE { 75 | ULONG Valid : 1; 76 | ULONG PageFileLow : 4; 77 | ULONG Protection : 5; 78 | ULONG Prototype : 1; 79 | ULONG Transition : 1; 80 | ULONG PageFileHigh : 20; 81 | } MMPTE_SOFTWARE; 82 | 83 | typedef struct _MMPTE_TRANSITION { 84 | ULONG Valid : 1; 85 | ULONG Write : 1; 86 | ULONG Owner : 1; 87 | ULONG WriteThrough : 1; 88 | ULONG CacheDisable : 1; 89 | ULONG Protection : 5; 90 | ULONG Prototype : 1; 91 | ULONG Transition : 1; 92 | ULONG PageFrameNumber : 20; 93 | } MMPTE_TRANSITION; 94 | 95 | typedef struct _MMPTE_PROTOTYPE { 96 | ULONG Valid : 1; 97 | ULONG ProtoAddressLow : 7; 98 | ULONG ReadOnly : 1; // if set allow read only access. 99 | ULONG WhichPool : 1; 100 | ULONG Prototype : 1; 101 | ULONG ProtoAddressHigh : 21; 102 | } MMPTE_PROTOTYPE; 103 | 104 | typedef struct _MMPTE_HARDWARE { 105 | ULONG Valid : 1; 106 | ULONG Write : 1; // UP version 107 | ULONG Owner : 1; 108 | ULONG WriteThrough : 1; 109 | ULONG CacheDisable : 1; 110 | ULONG Accessed : 1; 111 | ULONG Dirty : 1; 112 | ULONG LargePage : 1; 113 | ULONG Global : 1; 114 | ULONG CopyOnWrite : 1; // software field 115 | ULONG Prototype : 1; // software field 116 | ULONG reserved : 1; // software field 117 | ULONG PageFrameNumber : 20; 118 | } MMPTE_HARDWARE, *PMMPTE_HARDWARE; 119 | 120 | typedef struct _MMPTE { 121 | union { 122 | ULONG Long; 123 | MMPTE_HARDWARE Hard; 124 | MMPTE_PROTOTYPE Proto; 125 | MMPTE_SOFTWARE Soft; 126 | MMPTE_TRANSITION Trans; 127 | } u; 128 | } MMPTE, *PMMPTE; 129 | 130 | typedef struct _MMPTE_SOFTWARE_PAE { 131 | ULONGLONG Valid : 1; 132 | ULONGLONG PageFileLow : 4; 133 | ULONGLONG Protection : 5; 134 | ULONGLONG Prototype : 1; 135 | ULONGLONG Transition : 1; 136 | ULONGLONG Unused : 20; 137 | ULONGLONG PageFileHigh : 32; 138 | } MMPTE_SOFTWARE_PAE; 139 | 140 | typedef struct _MMPTE_TRANSITION_PAE { 141 | ULONGLONG Valid : 1; 142 | ULONGLONG Write : 1; 143 | ULONGLONG Owner : 1; 144 | ULONGLONG WriteThrough : 1; 145 | ULONGLONG CacheDisable : 1; 146 | ULONGLONG Protection : 5; 147 | ULONGLONG Prototype : 1; 148 | ULONGLONG Transition : 1; 149 | ULONGLONG PageFrameNumber : 24; 150 | ULONGLONG Unused : 28; 151 | } MMPTE_TRANSITION_PAE; 152 | 153 | typedef struct _MMPTE_PROTOTYPE_PAE { 154 | ULONGLONG Valid : 1; 155 | ULONGLONG Unused0: 7; 156 | ULONGLONG ReadOnly : 1; // if set allow read only access. LWFIX: remove 157 | ULONGLONG Unused1: 1; 158 | ULONGLONG Prototype : 1; 159 | ULONGLONG Protection : 5; 160 | ULONGLONG Unused: 16; 161 | ULONGLONG ProtoAddress: 32; 162 | } MMPTE_PROTOTYPE_PAE; 163 | 164 | typedef struct _MMPTE_HARDWARE_PAE { 165 | ULONGLONG Valid : 1; 166 | ULONGLONG Write : 1; // UP version 167 | ULONGLONG Owner : 1; 168 | ULONGLONG WriteThrough : 1; 169 | ULONGLONG CacheDisable : 1; 170 | ULONGLONG Accessed : 1; 171 | ULONGLONG Dirty : 1; 172 | ULONGLONG LargePage : 1; 173 | ULONGLONG Global : 1; 174 | ULONGLONG CopyOnWrite : 1; // software field 175 | ULONGLONG Prototype : 1; // software field 176 | ULONGLONG reserved0 : 1; // software field 177 | ULONGLONG PageFrameNumber : 24; 178 | ULONGLONG reserved1 : 28; // software field 179 | } MMPTE_HARDWARE_PAE, *PMMPTE_HARDWARE_PAE; 180 | 181 | typedef struct _MMPTE_PAE 182 | { 183 | union 184 | { 185 | LARGE_INTEGER Long; 186 | MMPTE_HARDWARE_PAE Hard; 187 | MMPTE_PROTOTYPE_PAE Proto; 188 | MMPTE_SOFTWARE_PAE Soft; 189 | MMPTE_TRANSITION_PAE Trans; 190 | } u; 191 | } MMPTE_PAE; 192 | typedef MMPTE_PAE *PMMPTE_PAE; 193 | #define PTE_BASE 0xC0000000 194 | #define PDE_BASE 0xC0300000 195 | #define PDE_BASE_PAE 0xc0600000 196 | 197 | #define MiGetPteAddressPae(va) ((PMMPTE_PAE)(PTE_BASE + ((((ULONG)(va)) >> 12) << 3))) 198 | #define MiGetPdeAddressPae(va) ((PMMPTE_PAE)(PDE_BASE_PAE + ((((ULONG)(va)) >> 21) << 3))) 199 | #define MiGetPdeAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE)) 200 | #define MiGetPteAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE)) 201 | 202 | typedef struct _SERVICE_DESCRIPTOR_TABLE 203 | { 204 | PDWORD ServiceTable; 205 | PULONG CounterTable; 206 | ULONG TableSize; 207 | PUCHAR ArgumentTable; 208 | } SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; 209 | 210 | #pragma pack(pop) 211 | 212 | extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; 213 | -------------------------------------------------------------------------------- /VersionSelector.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LPC", "LPC\LPC.vcxproj", "{37046609-CBFD-4108-9AC4-6513E7022059}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoServer", "DemoServer\DemoServer.vcxproj", "{70266E3C-6B66-4EE5-A090-73923396A0EC}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {37046609-CBFD-4108-9AC4-6513E7022059} = {37046609-CBFD-4108-9AC4-6513E7022059} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoClient", "DemoClient\DemoClient.vcxproj", "{40C8E5DC-800D-4181-88CB-489972879FB3}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {37046609-CBFD-4108-9AC4-6513E7022059} = {37046609-CBFD-4108-9AC4-6513E7022059} 14 | EndProjectSection 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LPCTest", "LPCTest\LPCTest.vcxproj", "{4E179CE6-6B91-4B05-9770-57E6AA4C9801}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug x64|Win32 = Debug x64|Win32 21 | Debug x64|x64 = Debug x64|x64 22 | Debug x86|Win32 = Debug x86|Win32 23 | Debug x86|x64 = Debug x86|x64 24 | Release|Win32 = Release|Win32 25 | Release|x64 = Release|x64 26 | x86 kernel|Win32 = x86 kernel|Win32 27 | x86 kernel|x64 = x86 kernel|x64 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 31 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x64|Win32.Build.0 = Debug x64|Win32 32 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x64|x64.ActiveCfg = Debug x64|x64 33 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x64|x64.Build.0 = Debug x64|x64 34 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x86|Win32.ActiveCfg = Debug x86|Win32 35 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x86|Win32.Build.0 = Debug x86|Win32 36 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x86|x64.ActiveCfg = Debug x86|x64 37 | {37046609-CBFD-4108-9AC4-6513E7022059}.Debug x86|x64.Build.0 = Debug x86|x64 38 | {37046609-CBFD-4108-9AC4-6513E7022059}.Release|Win32.ActiveCfg = Release|Win32 39 | {37046609-CBFD-4108-9AC4-6513E7022059}.Release|Win32.Build.0 = Release|Win32 40 | {37046609-CBFD-4108-9AC4-6513E7022059}.Release|x64.ActiveCfg = Release|x64 41 | {37046609-CBFD-4108-9AC4-6513E7022059}.Release|x64.Build.0 = Release|x64 42 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|Win32.ActiveCfg = x86 kernel|Win32 43 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|Win32.Build.0 = x86 kernel|Win32 44 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|Win32.Deploy.0 = x86 kernel|Win32 45 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|x64.ActiveCfg = x86 kernel|x64 46 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|x64.Build.0 = x86 kernel|x64 47 | {37046609-CBFD-4108-9AC4-6513E7022059}.x86 kernel|x64.Deploy.0 = x86 kernel|x64 48 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 49 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x64|Win32.Build.0 = Debug x64|Win32 50 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x64|x64.ActiveCfg = Debug x64|x64 51 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x64|x64.Build.0 = Debug x64|x64 52 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x86|Win32.ActiveCfg = Debug x86|Win32 53 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x86|Win32.Build.0 = Debug x86|Win32 54 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x86|x64.ActiveCfg = Debug x86|x64 55 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Debug x86|x64.Build.0 = Debug x86|x64 56 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Release|Win32.ActiveCfg = Release|Win32 57 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Release|Win32.Build.0 = Release|Win32 58 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Release|x64.ActiveCfg = Release|x64 59 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.Release|x64.Build.0 = Release|x64 60 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.x86 kernel|Win32.ActiveCfg = x86 kernel|Win32 61 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.x86 kernel|x64.ActiveCfg = x86 kernel|x64 62 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.x86 kernel|x64.Build.0 = x86 kernel|x64 63 | {70266E3C-6B66-4EE5-A090-73923396A0EC}.x86 kernel|x64.Deploy.0 = x86 kernel|x64 64 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 65 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x64|Win32.Build.0 = Debug x64|Win32 66 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x64|x64.ActiveCfg = Debug x64|x64 67 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x64|x64.Build.0 = Debug x64|x64 68 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x86|Win32.ActiveCfg = Debug x86|Win32 69 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x86|Win32.Build.0 = Debug x86|Win32 70 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x86|x64.ActiveCfg = Debug x86|x64 71 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Debug x86|x64.Build.0 = Debug x86|x64 72 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Release|Win32.ActiveCfg = Release|Win32 73 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Release|Win32.Build.0 = Release|Win32 74 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Release|x64.ActiveCfg = Release|x64 75 | {40C8E5DC-800D-4181-88CB-489972879FB3}.Release|x64.Build.0 = Release|x64 76 | {40C8E5DC-800D-4181-88CB-489972879FB3}.x86 kernel|Win32.ActiveCfg = x86 kernel|Win32 77 | {40C8E5DC-800D-4181-88CB-489972879FB3}.x86 kernel|x64.ActiveCfg = x86 kernel|x64 78 | {40C8E5DC-800D-4181-88CB-489972879FB3}.x86 kernel|x64.Build.0 = x86 kernel|x64 79 | {40C8E5DC-800D-4181-88CB-489972879FB3}.x86 kernel|x64.Deploy.0 = x86 kernel|x64 80 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x64|Win32.ActiveCfg = x86 kernel|Win32 81 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x64|Win32.Deploy.0 = x86 kernel|Win32 82 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x64|x64.ActiveCfg = x86 kernel|x64 83 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x64|x64.Build.0 = x86 kernel|x64 84 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x64|x64.Deploy.0 = x86 kernel|x64 85 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x86|Win32.ActiveCfg = x86 kernel|Win32 86 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x86|Win32.Deploy.0 = x86 kernel|Win32 87 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x86|x64.ActiveCfg = x86 kernel|x64 88 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x86|x64.Build.0 = x86 kernel|x64 89 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Debug x86|x64.Deploy.0 = x86 kernel|x64 90 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|Win32.ActiveCfg = x86 kernel|Win32 91 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|Win32.Build.0 = x86 kernel|Win32 92 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|Win32.Deploy.0 = x86 kernel|Win32 93 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|x64.ActiveCfg = x86 kernel|x64 94 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|x64.Build.0 = x86 kernel|x64 95 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.Release|x64.Deploy.0 = x86 kernel|x64 96 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.x86 kernel|Win32.ActiveCfg = x86 kernel|Win32 97 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.x86 kernel|Win32.Build.0 = x86 kernel|Win32 98 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.x86 kernel|x64.ActiveCfg = x86 kernel|x64 99 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.x86 kernel|x64.Build.0 = x86 kernel|x64 100 | {4E179CE6-6B91-4B05-9770-57E6AA4C9801}.x86 kernel|x64.Deploy.0 = x86 kernel|x64 101 | EndGlobalSection 102 | GlobalSection(SolutionProperties) = preSolution 103 | HideSolutionNode = FALSE 104 | EndGlobalSection 105 | EndGlobal 106 | -------------------------------------------------------------------------------- /LPC/LPC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define SERVERNAME_W L"\\AAAAAAAAAAAAAAAAA" 4 | #define SERVERNAME_A "\\AAAAAAAAAAAAAAAAA" 5 | 6 | #define LARGE_MESSAGE_SIZE 0x9000 7 | 8 | #include "CommonDefs.h" 9 | 10 | #pragma pack(push,1) 11 | #ifndef _KERNEL_MODE 12 | #define PRINT(...) _tprintf(__VA_ARGS__) 13 | #define STRLEN _tcslen 14 | #define STRCOPY wcscpy_s 15 | #else 16 | #pragma comment(lib,"Ntstrsafe.lib") 17 | #include "..\inc\uthash.h" 18 | #define PRINT(...) KdPrint((__VA_ARGS__)) 19 | #define _T 20 | 21 | FORCEINLINE size_t SafeStrlen(LPCTSTR str) 22 | { 23 | size_t size; 24 | NTSTATUS status = RtlStringCchLengthW((STRSAFE_PCNZWCH)str,NTSTRSAFE_MAX_CCH,&size); 25 | if (NT_SUCCESS(status)) 26 | return size; 27 | else 28 | return 0; 29 | } 30 | FORCEINLINE VOID SafeStrCopy(LPTSTR pszDest,size_t cchDest,LPCTSTR pszSrc) 31 | { 32 | NTSTATUS status = RtlStringCchCopyW((NTSTRSAFE_PWSTR)pszDest,cchDest,(NTSTRSAFE_PCWSTR)pszSrc); 33 | if (!NT_SUCCESS(status)) 34 | *pszDest = '\0'; 35 | } 36 | 37 | #define STRLEN(x) SafeStrlen(x) 38 | #define STRCOPY(a,b) SafeStrCopy((LPTSTR)a,SafeStrlen((LPCTSTR)b)*sizeof(LPCTSTR),(LPCTSTR)b) 39 | 40 | #endif 41 | 42 | 43 | #define OBJ_KERNEL_HANDLE 0x00000200L 44 | 45 | 46 | #define LPC_COMMAND_REQUEST_NOREPLY 0x00000000 47 | #define LPC_COMMAND_REQUEST_REPLY 0x00000001 48 | #define LPC_COMMAND_STOP 0x00000002 49 | #define LPC_COMMAND_RESERVE 0x00000100 50 | 51 | // user define command should be (LPC_COMMAND_RESERVE < x <= 0x7FFFFFFF) 52 | #define IS_COMMAND_RESERVE(x) ((x) <= LPC_COMMAND_RESERVE) 53 | #define IS_COMMAND_ASYNC(x) ((x) & 0x80000000) //1 bit to decide async or sync 54 | #define SET_COMMAND(x,y) x = (((x) & 0x7FFFFFFF) | ((y) << 31)) 55 | #define GET_COMMAND(x) x = ((x) & 0x7FFFFFFF) 56 | 57 | // This is the data structure transferred through LPC. 58 | // Every structure must begin with PORT_MESSAGE, and must NOT be 59 | // greater that MAX_LPC_DATA 60 | 61 | #ifdef _M_X64 62 | #define MAX_LPC_DATA 0x120 63 | #else 64 | #define MAX_LPC_DATA 0x130 65 | #endif // _M_IA64 66 | 67 | //(MaxData <= 0x104) and (MaxTotal <= 0x148) 68 | #define MAX_MESSAGE_SIZE 0xFE 69 | typedef struct _TRANSFERRED_MESSAGE 70 | { 71 | PORT_MESSAGE Header; // (0x18 -- x86)(0x28 -- x64) 72 | 73 | //ULONG Reserve; // this byte must be 0, or you get STATUS_INVALID_PARAMETER 74 | ULONG Command; // 4 byte 75 | BOOLEAN UseSection; // 1 byte 76 | WCHAR MessageText[127]; // 125*2 = 0xFE 77 | // 0x1 + 0x4 + 0xFE = 0x103 <= 0x104 78 | 79 | } TRANSFERRED_MESSAGE, *PTRANSFERRED_MESSAGE; 80 | 81 | 82 | typedef enum _LPC_TYPE { 83 | LPC_NEW_MESSAGE, // A new message 84 | LPC_REQUEST, // A request message 85 | LPC_REPLY, // A reply to a request message 86 | LPC_DATAGRAM, // 87 | LPC_LOST_REPLY, // 88 | LPC_PORT_CLOSED, // Sent when port is deleted 89 | LPC_CLIENT_DIED, // Messages to thread termination ports 90 | LPC_EXCEPTION, // Messages to thread exception port 91 | LPC_DEBUG_EVENT, // Messages to thread debug port 92 | LPC_ERROR_EVENT, // Used by ZwRaiseHardError 93 | LPC_CONNECTION_REQUEST // Used by ZwConnectPort 94 | } LPC_TYPE; 95 | 96 | enum ControlMethod 97 | { 98 | SYNC = 0, 99 | ASYNC = 1 100 | }; 101 | 102 | #ifndef InitializeMessageHeader 103 | #define InitializeMessageHeader(ph, l, t) \ 104 | { \ 105 | (ph)->u1.s1.TotalLength = (USHORT)(l); \ 106 | (ph)->u1.s1.DataLength = (USHORT)(l - sizeof(PORT_MESSAGE)); \ 107 | (ph)->u2.s2.Type = (USHORT)(t); \ 108 | (ph)->u2.s2.DataInfoOffset = 0; \ 109 | (ph)->ClientId.UniqueProcess = NULL; \ 110 | (ph)->ClientId.UniqueThread = NULL; \ 111 | (ph)->MessageId = 0; \ 112 | (ph)->ClientViewSize = 0; \ 113 | } 114 | #endif 115 | 116 | 117 | //unexported functions declare 118 | 119 | typedef NTSTATUS (NTAPI* _CreatePort)( 120 | OUT PHANDLE PortHandle, 121 | IN POBJECT_ATTRIBUTES ObjectAttributes, 122 | IN ULONG MaxConnectionInfoLength, 123 | IN ULONG MaxMessageLength, 124 | IN ULONG MaxPoolUsage 125 | ); 126 | 127 | 128 | typedef NTSTATUS (NTAPI* _ConnectPort)( 129 | OUT PHANDLE PortHandle, 130 | IN PUNICODE_STRING PortName, 131 | IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, 132 | IN OUT PPORT_VIEW ClientView OPTIONAL, 133 | OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, 134 | OUT PULONG MaxMessageLength OPTIONAL, 135 | IN OUT PVOID ConnectInformation OPTIONAL, 136 | IN OUT PULONG ConnectInformationLength OPTIONAL 137 | ); 138 | 139 | 140 | typedef NTSTATUS (NTAPI* _ListenPort)( 141 | IN HANDLE PortHandle, 142 | OUT PPORT_MESSAGE Message 143 | ); 144 | 145 | 146 | typedef NTSTATUS (NTAPI* _AcceptConnectPort)( 147 | OUT PHANDLE PortHandle, 148 | IN PVOID PortIdentifier, 149 | IN PPORT_MESSAGE Message, 150 | IN BOOLEAN Accept, 151 | IN OUT PPORT_VIEW ServerView OPTIONAL, 152 | OUT PREMOTE_PORT_VIEW ClientView OPTIONAL 153 | ); 154 | 155 | 156 | typedef NTSTATUS (NTAPI* _CompleteConnectPort)( 157 | IN HANDLE PortHandle 158 | ); 159 | 160 | typedef NTSTATUS (NTAPI* _ReplyPort)( 161 | IN HANDLE PortHandle, 162 | IN PPORT_MESSAGE ReplyMessage 163 | ); 164 | 165 | 166 | typedef NTSTATUS (NTAPI* _ReplyWaitReceivePort)( 167 | IN HANDLE PortHandle, 168 | OUT PULONG PortIdentifier OPTIONAL, 169 | IN PPORT_MESSAGE ReplyMessage OPTIONAL, 170 | OUT PPORT_MESSAGE Message 171 | ); 172 | 173 | 174 | typedef NTSTATUS (NTAPI* _ReplyWaitReceivePortEx)( 175 | IN HANDLE PortHandle, 176 | OUT PVOID* PortIdentifier OPTIONAL, 177 | IN PPORT_MESSAGE ReplyMessage OPTIONAL, 178 | OUT PPORT_MESSAGE Message, 179 | IN PLARGE_INTEGER Timeout 180 | ); 181 | 182 | typedef NTSTATUS (NTAPI* _RequestPort)( 183 | IN HANDLE PortHandle, 184 | IN PPORT_MESSAGE RequestMessage 185 | ); 186 | 187 | 188 | typedef NTSTATUS (NTAPI* _RequestWaitReplyPort)( 189 | IN HANDLE PortHandle, 190 | IN PPORT_MESSAGE RequestMessage, 191 | OUT PPORT_MESSAGE ReplyMessage 192 | ); 193 | 194 | typedef NTSTATUS (NTAPI *_ZwCreateSection)( 195 | _Out_ PHANDLE SectionHandle, 196 | _In_ ACCESS_MASK DesiredAccess, 197 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 198 | _In_opt_ PLARGE_INTEGER MaximumSize, 199 | _In_ ULONG SectionPageProtection, 200 | _In_ ULONG AllocationAttributes, 201 | _In_opt_ HANDLE FileHandle 202 | ); 203 | 204 | //http://troydhanson.github.io/uthash/userguide.html 205 | #ifdef _KERNEL_MODE 206 | typedef struct _KERNEL_MAP 207 | { 208 | int command; // key 209 | PVOID callback; 210 | UT_hash_handle hh; // make this structure hashable 211 | } KERNEL_MAP,*PKERNEL_MAP; 212 | #else 213 | void Control( ULONG COMMAND,ULONG method, TCHAR *msg ); 214 | #endif 215 | 216 | typedef struct _CLIENT_ENTRY 217 | { 218 | LIST_ENTRY List; 219 | HANDLE ClientHandle; // data port 220 | REMOTE_PORT_VIEW ClientView; 221 | } CLIENT_ENTRY,*PCLIENT_ENTRY; 222 | 223 | typedef struct _SERVER_INFO 224 | { 225 | HANDLE LPCPortHandle; // connection port 226 | HANDLE SectionHandle; 227 | HANDLE ServerThreadHandle; // Server thread handle 228 | PORT_VIEW ServerView; 229 | //#ifdef _KERNEL_MODE 230 | // KERNEL_MAP *CallBackList; 231 | //#endif 232 | }SERVER_INFO,*PSERVER_INFO; 233 | 234 | typedef struct _CLIENT_INFO 235 | { 236 | HANDLE ServerHandle; //data port 237 | PORT_VIEW ClientView; 238 | REMOTE_PORT_VIEW ServerView; 239 | }CLIENT_INFO,*PCLIENT_INFO; 240 | 241 | //data type 242 | #define DATA_NOTIFY_SHUTDOWN 1 243 | #define DATA_TRANSFER_CHATTING 2 244 | #define DATA_TRANSFER_PROCESSS 3 245 | 246 | 247 | #ifndef _KERNEL_MODE 248 | #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 249 | #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 250 | #else 251 | extern ULONG m_AllocTag; 252 | #define MALLOC(x) ExAllocatePoolWithTag(PagedPool,x,m_AllocTag) 253 | #define FREE(x) ExFreePoolWithTag(x,m_AllocTag) 254 | #endif 255 | 256 | 257 | void InsertCallBack(ULONG command,PVOID callback); 258 | void runServer(TCHAR *ServerName); 259 | BOOL Connect(TCHAR *ServerName); 260 | BOOL AsyncSend(TCHAR *msg); 261 | BOOL SyncSend(TCHAR *msg); 262 | BOOL Send(TCHAR *msg,ULONG command); 263 | void StopServer(TCHAR *); 264 | 265 | #pragma pack(pop) 266 | -------------------------------------------------------------------------------- /inc/utstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | /* a dynamic string implementation using macros 25 | */ 26 | #ifndef UTSTRING_H 27 | #define UTSTRING_H 28 | 29 | #define UTSTRING_VERSION 1.9.8 30 | 31 | #ifdef __GNUC__ 32 | #define _UNUSED_ __attribute__ ((__unused__)) 33 | #else 34 | #define _UNUSED_ 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #define oom() exit(-1) 41 | 42 | typedef struct { 43 | char *d; 44 | size_t n; /* allocd size */ 45 | size_t i; /* index of first unused byte */ 46 | } UT_string; 47 | 48 | #define utstring_reserve(s,amt) \ 49 | do { \ 50 | if (((s)->n - (s)->i) < (size_t)(amt)) { \ 51 | (s)->d = (char*)realloc((s)->d, (s)->n + amt); \ 52 | if ((s)->d == NULL) oom(); \ 53 | (s)->n += amt; \ 54 | } \ 55 | } while(0) 56 | 57 | #define utstring_init(s) \ 58 | do { \ 59 | (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ 60 | utstring_reserve(s,100); \ 61 | (s)->d[0] = '\0'; \ 62 | } while(0) 63 | 64 | #define utstring_done(s) \ 65 | do { \ 66 | if ((s)->d != NULL) free((s)->d); \ 67 | (s)->n = 0; \ 68 | } while(0) 69 | 70 | #define utstring_free(s) \ 71 | do { \ 72 | utstring_done(s); \ 73 | free(s); \ 74 | } while(0) 75 | 76 | #define utstring_new(s) \ 77 | do { \ 78 | s = (UT_string*)calloc(sizeof(UT_string),1); \ 79 | if (!s) oom(); \ 80 | utstring_init(s); \ 81 | } while(0) 82 | 83 | #define utstring_renew(s) \ 84 | do { \ 85 | if (s) { \ 86 | utstring_clear(s); \ 87 | } else { \ 88 | utstring_new(s); \ 89 | } \ 90 | } while(0) 91 | 92 | #define utstring_clear(s) \ 93 | do { \ 94 | (s)->i = 0; \ 95 | (s)->d[0] = '\0'; \ 96 | } while(0) 97 | 98 | #define utstring_bincpy(s,b,l) \ 99 | do { \ 100 | utstring_reserve((s),(l)+1); \ 101 | if (l) memcpy(&(s)->d[(s)->i], b, l); \ 102 | (s)->i += l; \ 103 | (s)->d[(s)->i]='\0'; \ 104 | } while(0) 105 | 106 | #define utstring_concat(dst,src) \ 107 | do { \ 108 | utstring_reserve((dst),((src)->i)+1); \ 109 | if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ 110 | (dst)->i += (src)->i; \ 111 | (dst)->d[(dst)->i]='\0'; \ 112 | } while(0) 113 | 114 | #define utstring_len(s) ((unsigned)((s)->i)) 115 | 116 | #define utstring_body(s) ((s)->d) 117 | 118 | _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { 119 | int n; 120 | va_list cp; 121 | while (1) { 122 | #ifdef _WIN32 123 | cp = ap; 124 | #else 125 | va_copy(cp, ap); 126 | #endif 127 | n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); 128 | va_end(cp); 129 | 130 | if ((n > -1) && (n < (int)(s->n-s->i))) { 131 | s->i += n; 132 | return; 133 | } 134 | 135 | /* Else try again with more space. */ 136 | if (n > -1) utstring_reserve(s,n+1); /* exact */ 137 | else utstring_reserve(s,(s->n)*2); /* 2x */ 138 | } 139 | } 140 | #ifdef __GNUC__ 141 | /* support printf format checking (2=the format string, 3=start of varargs) */ 142 | static void utstring_printf(UT_string *s, const char *fmt, ...) 143 | __attribute__ (( format( printf, 2, 3) )); 144 | #endif 145 | _UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) { 146 | va_list ap; 147 | va_start(ap,fmt); 148 | utstring_printf_va(s,fmt,ap); 149 | va_end(ap); 150 | } 151 | 152 | /******************************************************************************* 153 | * begin substring search functions * 154 | ******************************************************************************/ 155 | /* Build KMP table from left to right. */ 156 | _UNUSED_ static void _utstring_BuildTable( 157 | const char *P_Needle, 158 | size_t P_NeedleLen, 159 | long *P_KMP_Table) 160 | { 161 | long i, j; 162 | 163 | i = 0; 164 | j = i - 1; 165 | P_KMP_Table[i] = j; 166 | while (i < P_NeedleLen) 167 | { 168 | while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) 169 | { 170 | j = P_KMP_Table[j]; 171 | } 172 | i++; 173 | j++; 174 | if (i < P_NeedleLen) 175 | { 176 | if (P_Needle[i] == P_Needle[j]) 177 | { 178 | P_KMP_Table[i] = P_KMP_Table[j]; 179 | } 180 | else 181 | { 182 | P_KMP_Table[i] = j; 183 | } 184 | } 185 | else 186 | { 187 | P_KMP_Table[i] = j; 188 | } 189 | } 190 | 191 | return; 192 | } 193 | 194 | 195 | /* Build KMP table from right to left. */ 196 | _UNUSED_ static void _utstring_BuildTableR( 197 | const char *P_Needle, 198 | size_t P_NeedleLen, 199 | long *P_KMP_Table) 200 | { 201 | long i, j; 202 | 203 | i = P_NeedleLen - 1; 204 | j = i + 1; 205 | P_KMP_Table[i + 1] = j; 206 | while (i >= 0) 207 | { 208 | while ( (j < P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) 209 | { 210 | j = P_KMP_Table[j + 1]; 211 | } 212 | i--; 213 | j--; 214 | if (i >= 0) 215 | { 216 | if (P_Needle[i] == P_Needle[j]) 217 | { 218 | P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; 219 | } 220 | else 221 | { 222 | P_KMP_Table[i + 1] = j; 223 | } 224 | } 225 | else 226 | { 227 | P_KMP_Table[i + 1] = j; 228 | } 229 | } 230 | 231 | return; 232 | } 233 | 234 | 235 | /* Search data from left to right. ( Multiple search mode. ) */ 236 | _UNUSED_ static long _utstring_find( 237 | const char *P_Haystack, 238 | size_t P_HaystackLen, 239 | const char *P_Needle, 240 | size_t P_NeedleLen, 241 | long *P_KMP_Table) 242 | { 243 | long i, j; 244 | long V_FindPosition = -1; 245 | 246 | /* Search from left to right. */ 247 | i = j = 0; 248 | while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) 249 | { 250 | while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) 251 | { 252 | i = P_KMP_Table[i]; 253 | } 254 | i++; 255 | j++; 256 | if (i >= (int)P_NeedleLen) 257 | { 258 | /* Found. */ 259 | V_FindPosition = j - i; 260 | break; 261 | } 262 | } 263 | 264 | return V_FindPosition; 265 | } 266 | 267 | 268 | /* Search data from right to left. ( Multiple search mode. ) */ 269 | _UNUSED_ static long _utstring_findR( 270 | const char *P_Haystack, 271 | size_t P_HaystackLen, 272 | const char *P_Needle, 273 | size_t P_NeedleLen, 274 | long *P_KMP_Table) 275 | { 276 | long i, j; 277 | long V_FindPosition = -1; 278 | 279 | /* Search from right to left. */ 280 | j = (P_HaystackLen - 1); 281 | i = (P_NeedleLen - 1); 282 | while ( (j >= 0) && (j >= i) ) 283 | { 284 | while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) 285 | { 286 | i = P_KMP_Table[i + 1]; 287 | } 288 | i--; 289 | j--; 290 | if (i < 0) 291 | { 292 | /* Found. */ 293 | V_FindPosition = j + 1; 294 | break; 295 | } 296 | } 297 | 298 | return V_FindPosition; 299 | } 300 | 301 | 302 | /* Search data from left to right. ( One time search mode. ) */ 303 | _UNUSED_ static long utstring_find( 304 | UT_string *s, 305 | long P_StartPosition, /* Start from 0. -1 means last position. */ 306 | const char *P_Needle, 307 | size_t P_NeedleLen) 308 | { 309 | long V_StartPosition; 310 | long V_HaystackLen; 311 | long *V_KMP_Table; 312 | long V_FindPosition = -1; 313 | 314 | if (P_StartPosition < 0) 315 | { 316 | V_StartPosition = s->i + P_StartPosition; 317 | } 318 | else 319 | { 320 | V_StartPosition = P_StartPosition; 321 | } 322 | V_HaystackLen = s->i - V_StartPosition; 323 | if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) 324 | { 325 | V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); 326 | if (V_KMP_Table != NULL) 327 | { 328 | _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); 329 | 330 | V_FindPosition = _utstring_find(s->d + V_StartPosition, 331 | V_HaystackLen, 332 | P_Needle, 333 | P_NeedleLen, 334 | V_KMP_Table); 335 | if (V_FindPosition >= 0) 336 | { 337 | V_FindPosition += V_StartPosition; 338 | } 339 | 340 | free(V_KMP_Table); 341 | } 342 | } 343 | 344 | return V_FindPosition; 345 | } 346 | 347 | 348 | /* Search data from right to left. ( One time search mode. ) */ 349 | _UNUSED_ static long utstring_findR( 350 | UT_string *s, 351 | long P_StartPosition, /* Start from 0. -1 means last position. */ 352 | const char *P_Needle, 353 | size_t P_NeedleLen) 354 | { 355 | long V_StartPosition; 356 | long V_HaystackLen; 357 | long *V_KMP_Table; 358 | long V_FindPosition = -1; 359 | 360 | if (P_StartPosition < 0) 361 | { 362 | V_StartPosition = s->i + P_StartPosition; 363 | } 364 | else 365 | { 366 | V_StartPosition = P_StartPosition; 367 | } 368 | V_HaystackLen = V_StartPosition + 1; 369 | if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) 370 | { 371 | V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); 372 | if (V_KMP_Table != NULL) 373 | { 374 | _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); 375 | 376 | V_FindPosition = _utstring_findR(s->d, 377 | V_HaystackLen, 378 | P_Needle, 379 | P_NeedleLen, 380 | V_KMP_Table); 381 | 382 | free(V_KMP_Table); 383 | } 384 | } 385 | 386 | return V_FindPosition; 387 | } 388 | /******************************************************************************* 389 | * end substring search functions * 390 | ******************************************************************************/ 391 | 392 | #endif /* UTSTRING_H */ 393 | -------------------------------------------------------------------------------- /inc/utarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | /* a dynamic array implementation using macros 25 | */ 26 | #ifndef UTARRAY_H 27 | #define UTARRAY_H 28 | 29 | #define UTARRAY_VERSION 1.9.8 30 | 31 | #ifdef __GNUC__ 32 | #define _UNUSED_ __attribute__ ((__unused__)) 33 | #else 34 | #define _UNUSED_ 35 | #endif 36 | 37 | #include /* size_t */ 38 | #include /* memset, etc */ 39 | #include /* exit */ 40 | 41 | #define oom() exit(-1) 42 | 43 | typedef void (ctor_f)(void *dst, const void *src); 44 | typedef void (dtor_f)(void *elt); 45 | typedef void (init_f)(void *elt); 46 | typedef struct { 47 | size_t sz; 48 | init_f *init; 49 | ctor_f *copy; 50 | dtor_f *dtor; 51 | } UT_icd; 52 | 53 | typedef struct { 54 | unsigned i,n;/* i: index of next available slot, n: num slots */ 55 | UT_icd icd; /* initializer, copy and destructor functions */ 56 | char *d; /* n slots of size icd->sz*/ 57 | } UT_array; 58 | 59 | #define utarray_init(a,_icd) do { \ 60 | memset(a,0,sizeof(UT_array)); \ 61 | (a)->icd=*_icd; \ 62 | } while(0) 63 | 64 | #define utarray_done(a) do { \ 65 | if ((a)->n) { \ 66 | if ((a)->icd.dtor) { \ 67 | size_t _ut_i; \ 68 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 69 | (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ 70 | } \ 71 | } \ 72 | free((a)->d); \ 73 | } \ 74 | (a)->n=0; \ 75 | } while(0) 76 | 77 | #define utarray_new(a,_icd) do { \ 78 | a=(UT_array*)malloc(sizeof(UT_array)); \ 79 | utarray_init(a,_icd); \ 80 | } while(0) 81 | 82 | #define utarray_free(a) do { \ 83 | utarray_done(a); \ 84 | free(a); \ 85 | } while(0) 86 | 87 | #define utarray_reserve(a,by) do { \ 88 | if (((a)->i+by) > ((a)->n)) { \ 89 | while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ 90 | if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \ 91 | } \ 92 | } while(0) 93 | 94 | #define utarray_push_back(a,p) do { \ 95 | utarray_reserve(a,1); \ 96 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ 97 | else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ 98 | } while(0) 99 | 100 | #define utarray_pop_back(a) do { \ 101 | if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ 102 | else { (a)->i--; } \ 103 | } while(0) 104 | 105 | #define utarray_extend_back(a) do { \ 106 | utarray_reserve(a,1); \ 107 | if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ 108 | else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ 109 | (a)->i++; \ 110 | } while(0) 111 | 112 | #define utarray_len(a) ((a)->i) 113 | 114 | #define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) 115 | #define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) ))) 116 | 117 | #define utarray_insert(a,p,j) do { \ 118 | if (j > (a)->i) utarray_resize(a,j); \ 119 | utarray_reserve(a,1); \ 120 | if ((j) < (a)->i) { \ 121 | memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ 122 | ((a)->i - (j))*((a)->icd.sz)); \ 123 | } \ 124 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ 125 | else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ 126 | (a)->i++; \ 127 | } while(0) 128 | 129 | #define utarray_inserta(a,w,j) do { \ 130 | if (utarray_len(w) == 0) break; \ 131 | if (j > (a)->i) utarray_resize(a,j); \ 132 | utarray_reserve(a,utarray_len(w)); \ 133 | if ((j) < (a)->i) { \ 134 | memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ 135 | _utarray_eltptr(a,j), \ 136 | ((a)->i - (j))*((a)->icd.sz)); \ 137 | } \ 138 | if ((a)->icd.copy) { \ 139 | size_t _ut_i; \ 140 | for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ 141 | (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \ 142 | } \ 143 | } else { \ 144 | memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ 145 | utarray_len(w)*((a)->icd.sz)); \ 146 | } \ 147 | (a)->i += utarray_len(w); \ 148 | } while(0) 149 | 150 | #define utarray_resize(dst,num) do { \ 151 | size_t _ut_i; \ 152 | if (dst->i > (size_t)(num)) { \ 153 | if ((dst)->icd.dtor) { \ 154 | for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ 155 | (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ 156 | } \ 157 | } \ 158 | } else if (dst->i < (size_t)(num)) { \ 159 | utarray_reserve(dst,num-dst->i); \ 160 | if ((dst)->icd.init) { \ 161 | for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \ 162 | (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \ 163 | } \ 164 | } else { \ 165 | memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \ 166 | } \ 167 | } \ 168 | dst->i = num; \ 169 | } while(0) 170 | 171 | #define utarray_concat(dst,src) do { \ 172 | utarray_inserta((dst),(src),utarray_len(dst)); \ 173 | } while(0) 174 | 175 | #define utarray_erase(a,pos,len) do { \ 176 | if ((a)->icd.dtor) { \ 177 | size_t _ut_i; \ 178 | for(_ut_i=0; _ut_i < len; _ut_i++) { \ 179 | (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \ 180 | } \ 181 | } \ 182 | if ((a)->i > (pos+len)) { \ 183 | memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \ 184 | (((a)->i)-(pos+len))*((a)->icd.sz)); \ 185 | } \ 186 | (a)->i -= (len); \ 187 | } while(0) 188 | 189 | #define utarray_renew(a,u) do { \ 190 | if (a) utarray_clear(a); \ 191 | else utarray_new((a),(u)); \ 192 | } while(0) 193 | 194 | #define utarray_clear(a) do { \ 195 | if ((a)->i > 0) { \ 196 | if ((a)->icd.dtor) { \ 197 | size_t _ut_i; \ 198 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 199 | (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ 200 | } \ 201 | } \ 202 | (a)->i = 0; \ 203 | } \ 204 | } while(0) 205 | 206 | #define utarray_sort(a,cmp) do { \ 207 | qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ 208 | } while(0) 209 | 210 | #define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) 211 | 212 | #define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) 213 | #define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) 214 | #define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) 215 | #define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) 216 | #define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(ssize_t)(a)->icd.sz) : -1) 217 | 218 | /* last we pre-define a few icd for common utarrays of ints and strings */ 219 | static void utarray_str_cpy(void *dst, const void *src) { 220 | char **_src = (char**)src, **_dst = (char**)dst; 221 | *_dst = (*_src == NULL) ? NULL : strdup(*_src); 222 | } 223 | static void utarray_str_dtor(void *elt) { 224 | char **eltc = (char**)elt; 225 | if (*eltc) free(*eltc); 226 | } 227 | static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; 228 | static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL}; 229 | static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL}; 230 | 231 | 232 | #endif /* UTARRAY_H */ 233 | -------------------------------------------------------------------------------- /LPC/LPC.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug x64 6 | Win32 7 | 8 | 9 | Debug x64 10 | x64 11 | 12 | 13 | Debug x86 14 | Win32 15 | 16 | 17 | Debug x86 18 | x64 19 | 20 | 21 | Release 22 | Win32 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | x86 kernel 30 | Win32 31 | 32 | 33 | x86 kernel 34 | x64 35 | 36 | 37 | 38 | {37046609-CBFD-4108-9AC4-6513E7022059} 39 | Win32Proj 40 | LPC 41 | 42 | 43 | 44 | StaticLibrary 45 | true 46 | v110 47 | Unicode 48 | 49 | 50 | StaticLibrary 51 | true 52 | v110 53 | Unicode 54 | 55 | 56 | StaticLibrary 57 | true 58 | v110 59 | Unicode 60 | 61 | 62 | StaticLibrary 63 | true 64 | WindowsKernelModeDriver8.0 65 | Unicode 66 | 67 | 68 | StaticLibrary 69 | true 70 | v110 71 | Unicode 72 | 73 | 74 | StaticLibrary 75 | true 76 | v110 77 | Unicode 78 | 79 | 80 | StaticLibrary 81 | false 82 | v110 83 | true 84 | Unicode 85 | 86 | 87 | StaticLibrary 88 | false 89 | v110 90 | true 91 | Unicode 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ..\lib\$(Platform)\ 123 | $(Configuration)\ 124 | 125 | 126 | ..\lib\$(Platform)\ 127 | $(Configuration)\ 128 | 129 | 130 | ..\lib_r3\$(Platform)\ 131 | 132 | 133 | ..\lib\$(ConfigurationName)\ 134 | $(DDK_INC_PATH);$(IncludePath) 135 | $(LibraryPath) 136 | 137 | 138 | ..\lib\$(Platform)\ 139 | $(Configuration)\ 140 | 141 | 142 | D:\WinDDK\7600.16385.1\inc\wdf;D:\WinDDK\7600.16385.1\inc\mfc42;D:\WinDDK\7600.16385.1\inc\crt;D:\WinDDK\7600.16385.1\inc\atl71;D:\WinDDK\7600.16385.1\inc\api;D:\WinDDK\7600.16385.1\inc\ddk;$(IncludePath) 143 | ..\lib_r3\$(Platform)\ 144 | 145 | 146 | 147 | NotUsing 148 | Level3 149 | Disabled 150 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 151 | 152 | 153 | Windows 154 | true 155 | 156 | 157 | MachineX86 158 | 159 | 160 | 161 | 162 | NotUsing 163 | Level3 164 | Disabled 165 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 166 | 167 | 168 | Windows 169 | true 170 | 171 | 172 | MachineX86 173 | 174 | 175 | 176 | 177 | NotUsing 178 | Level3 179 | Disabled 180 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 181 | MultiThreadedDebug 182 | Sync 183 | CompileAsCpp 184 | 185 | 186 | Windows 187 | true 188 | 189 | 190 | MachineX86 191 | 192 | 193 | 194 | 195 | NotUsing 196 | Level3 197 | Disabled 198 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 199 | MultiThreadedDebug 200 | /kernel %(AdditionalOptions) 201 | 202 | 203 | Windows 204 | true 205 | 206 | 207 | MachineX86 208 | 209 | 210 | 211 | 212 | NotUsing 213 | Level3 214 | Disabled 215 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 216 | 217 | 218 | Windows 219 | true 220 | 221 | 222 | 223 | 224 | NotUsing 225 | Level3 226 | Disabled 227 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 228 | 229 | 230 | Windows 231 | true 232 | 233 | 234 | 235 | 236 | Level3 237 | Use 238 | MaxSpeed 239 | true 240 | true 241 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 242 | 243 | 244 | Windows 245 | true 246 | true 247 | true 248 | 249 | 250 | 251 | 252 | Level3 253 | Use 254 | MaxSpeed 255 | true 256 | true 257 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 258 | 259 | 260 | Windows 261 | true 262 | true 263 | true 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | CompileAsCpp 275 | 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /DemoClient/DemoClient.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug x64 6 | Win32 7 | 8 | 9 | Debug x64 10 | x64 11 | 12 | 13 | Debug x86 14 | Win32 15 | 16 | 17 | Debug x86 18 | x64 19 | 20 | 21 | Release 22 | Win32 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | x86 kernel 30 | Win32 31 | 32 | 33 | x86 kernel 34 | x64 35 | 36 | 37 | 38 | {40C8E5DC-800D-4181-88CB-489972879FB3} 39 | Win32Proj 40 | DemoClient 41 | 42 | 43 | 44 | Application 45 | true 46 | v110 47 | Unicode 48 | 49 | 50 | Application 51 | true 52 | v110 53 | Unicode 54 | 55 | 56 | Application 57 | true 58 | v110_xp 59 | Unicode 60 | 61 | 62 | Application 63 | true 64 | v110 65 | Unicode 66 | 67 | 68 | Application 69 | true 70 | v110 71 | Unicode 72 | 73 | 74 | Application 75 | true 76 | v110 77 | Unicode 78 | 79 | 80 | Application 81 | false 82 | v110 83 | true 84 | Unicode 85 | 86 | 87 | Application 88 | false 89 | v110 90 | true 91 | Unicode 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | true 123 | ..\bin\$(Platform)\ 124 | $(Configure)\ 125 | 126 | 127 | true 128 | ..\bin\$(Platform)\ 129 | $(Configure)\ 130 | 131 | 132 | true 133 | ..\bin\$(Platform)\ 134 | 135 | 136 | true 137 | ..\bin\$(Platform)\ 138 | 139 | 140 | true 141 | ..\bin\$(Platform)\ 142 | $(Configuration)\ 143 | 144 | 145 | true 146 | 147 | 148 | false 149 | ..\bin\$(Platform)\ 150 | $(Configure)\ 151 | 152 | 153 | false 154 | 155 | 156 | 157 | 158 | 159 | Level3 160 | Disabled 161 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 162 | 163 | 164 | Console 165 | true 166 | ..\lib\ 167 | 168 | 169 | 170 | 171 | 172 | 173 | Level3 174 | Disabled 175 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 176 | 177 | 178 | Console 179 | true 180 | ..\lib\ 181 | 182 | 183 | 184 | 185 | 186 | 187 | Level3 188 | Disabled 189 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 190 | MultiThreadedDebug 191 | EnableFastChecks 192 | 193 | 194 | Console 195 | true 196 | ..\lib_r3\$(Platform)\ 197 | RequireAdministrator 198 | 199 | 200 | 201 | 202 | 203 | 204 | Level3 205 | Disabled 206 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 207 | MultiThreadedDebug 208 | 209 | 210 | Console 211 | true 212 | ..\lib\$(Platform)\ 213 | 214 | 215 | 216 | 217 | 218 | 219 | Level3 220 | Disabled 221 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 222 | 223 | 224 | Console 225 | true 226 | ..\lib\$(Platform)\ 227 | 228 | 229 | 230 | 231 | 232 | 233 | Level3 234 | Disabled 235 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 236 | 237 | 238 | Console 239 | true 240 | ..\lib_r3\$(Platform)\ 241 | 242 | 243 | 244 | 245 | Level3 246 | 247 | 248 | MaxSpeed 249 | true 250 | true 251 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 252 | 253 | 254 | Console 255 | true 256 | true 257 | true 258 | 259 | 260 | 261 | 262 | Level3 263 | 264 | 265 | MaxSpeed 266 | true 267 | true 268 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 269 | 270 | 271 | Console 272 | true 273 | true 274 | true 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | -------------------------------------------------------------------------------- /DemoServer/DemoServer.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug x64 6 | Win32 7 | 8 | 9 | Debug x64 10 | x64 11 | 12 | 13 | Debug x86 14 | Win32 15 | 16 | 17 | Debug x86 18 | x64 19 | 20 | 21 | Release 22 | Win32 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | x86 kernel 30 | Win32 31 | 32 | 33 | x86 kernel 34 | x64 35 | 36 | 37 | 38 | {70266E3C-6B66-4EE5-A090-73923396A0EC} 39 | Win32Proj 40 | DemoServer 41 | 42 | 43 | 44 | Application 45 | true 46 | v110 47 | Unicode 48 | 49 | 50 | Application 51 | true 52 | v110 53 | Unicode 54 | 55 | 56 | Application 57 | true 58 | v110_xp 59 | Unicode 60 | 61 | 62 | Application 63 | true 64 | v110 65 | Unicode 66 | 67 | 68 | Application 69 | true 70 | v110 71 | Unicode 72 | 73 | 74 | Application 75 | true 76 | v110 77 | Unicode 78 | 79 | 80 | Application 81 | false 82 | v110 83 | true 84 | Unicode 85 | 86 | 87 | Application 88 | false 89 | v110 90 | true 91 | Unicode 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | true 123 | ..\bin\$(Platform) 124 | $(Configuration)\ 125 | 126 | 127 | true 128 | ..\bin\$(Platform) 129 | $(Configuration)\ 130 | 131 | 132 | true 133 | ..\bin\$(Platform)\ 134 | 135 | 136 | true 137 | ..\bin\$(Platform)\ 138 | 139 | 140 | true 141 | ..\bin\$(Platform)\ 142 | $(Configuration)\ 143 | 144 | 145 | true 146 | 147 | 148 | false 149 | 150 | 151 | false 152 | 153 | 154 | 155 | 156 | 157 | Level3 158 | Disabled 159 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 160 | 161 | 162 | Console 163 | true 164 | ..\lib\ 165 | RequireAdministrator 166 | 167 | 168 | 169 | 170 | 171 | 172 | Level3 173 | Disabled 174 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 175 | 176 | 177 | Console 178 | true 179 | ..\lib\ 180 | RequireAdministrator 181 | 182 | 183 | 184 | 185 | 186 | 187 | Level3 188 | Disabled 189 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 190 | MultiThreadedDebug 191 | 192 | 193 | Console 194 | true 195 | ..\lib_r3\$(Platform)\ 196 | RequireAdministrator 197 | 198 | 199 | 200 | 201 | 202 | 203 | Level3 204 | Disabled 205 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 206 | MultiThreadedDebug 207 | 208 | 209 | Console 210 | true 211 | ..\lib\$(Platform)\ 212 | RequireAdministrator 213 | 214 | 215 | 216 | 217 | 218 | 219 | Level3 220 | Disabled 221 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 222 | 223 | 224 | Console 225 | true 226 | ..\lib\$(Platform)\ 227 | RequireAdministrator 228 | 229 | 230 | 231 | 232 | 233 | 234 | Level3 235 | Disabled 236 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 237 | 238 | 239 | Console 240 | true 241 | ..\lib_r3\$(Platform)\ 242 | RequireAdministrator 243 | 244 | 245 | 246 | 247 | Level3 248 | 249 | 250 | MaxSpeed 251 | true 252 | true 253 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 254 | 255 | 256 | Console 257 | true 258 | true 259 | true 260 | 261 | 262 | 263 | 264 | Level3 265 | 266 | 267 | MaxSpeed 268 | true 269 | true 270 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 271 | 272 | 273 | Console 274 | true 275 | true 276 | true 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | -------------------------------------------------------------------------------- /LPC/LPC.c: -------------------------------------------------------------------------------- 1 | #include "LPC.h" 2 | 3 | _CreatePort NtCreatePort; 4 | _ListenPort NtListenPort; 5 | _AcceptConnectPort NtAcceptConnectPort; 6 | _CompleteConnectPort NtCompleteConnectPort; 7 | _ReplyPort NtReplyPort; 8 | _ReplyWaitReceivePort NtReplyWaitReceivePort; 9 | _ReplyWaitReceivePortEx NtReplyWaitReceivePortEx; 10 | _RequestPort NtRequestPort; 11 | _RequestWaitReplyPort NtRequestWaitReplyPort; 12 | _ConnectPort NtConnectPort; //exported 13 | #ifndef _KERNEL_MODE 14 | _InitUnicodeString RtlInitUnicodeString; 15 | _ZwCreateSection ZwCreateSection; 16 | 17 | MAP CallBackList; 18 | BOOL InitProcAddress(); 19 | BOOL CheckWOW64(); 20 | #else 21 | KERNEL_MAP *CallBackList; 22 | PVOID FindCallBack(ULONG command); 23 | BOOL FindKernelFunction(); 24 | #endif 25 | 26 | HANDLE hConnectPort; 27 | HANDLE SectionHandle; 28 | HANDLE hThread; 29 | SERVER_INFO si; 30 | CLIENT_INFO ci; 31 | LIST_ENTRY head; 32 | void ServerProc(SERVER_INFO *); 33 | BOOL KeepRunning; 34 | 35 | ULONG m_AllocTag = ' ZAR'; 36 | BOOL Debug = FALSE; 37 | 38 | #ifdef _KERNEL_MODE 39 | BOOL doKernelInit() 40 | { 41 | CallBackList = NULL;//MALLOC(sizeof(CallBackList)); 42 | return FindKernelFunction(); 43 | } 44 | #endif 45 | 46 | BOOL Initialize(void) 47 | { 48 | BOOL bOK = FALSE; 49 | RtlZeroMemory(&ci,sizeof(CLIENT_INFO)); 50 | RtlZeroMemory(&si,sizeof(SERVER_INFO)); 51 | #ifndef _KERNEL_MODE 52 | if (CheckWOW64()) 53 | { 54 | return bOK; 55 | } 56 | bOK = InitProcAddress(); 57 | #else 58 | // in kernel mode, must do initialize explicitly 59 | bOK = doKernelInit(); 60 | #endif 61 | return bOK; 62 | } 63 | 64 | #ifdef _KERNEL_MODE 65 | PVOID FindCallBack(ULONG command) 66 | { 67 | KERNEL_MAP *k; 68 | HASH_FIND_INT(CallBackList,&command,k); 69 | if (k == NULL) 70 | return NULL; 71 | else 72 | return k->callback; 73 | } 74 | #endif // _KERNEL_MODE 75 | 76 | void InsertCallBack(ULONG command,PVOID callback) 77 | { 78 | #ifdef _KERNEL_MODE 79 | KERNEL_MAP *k; 80 | if (!FindCallBack(command)) 81 | { 82 | k = (KERNEL_MAP *)MALLOC(sizeof(KERNEL_MAP)); 83 | k->command = command; 84 | k->callback = callback; 85 | HASH_ADD_INT(CallBackList,command,k); 86 | } 87 | #else 88 | CallBackList[command] = callback; 89 | #endif 90 | } 91 | 92 | 93 | void runServer(TCHAR *LpcPortName) 94 | { 95 | UNICODE_STRING usPortName; 96 | OBJECT_ATTRIBUTES obj; 97 | LARGE_INTEGER SectionSize = {LARGE_MESSAGE_SIZE}; 98 | 99 | if (LpcPortName == NULL) 100 | LpcPortName = (TCHAR *)SERVERNAME_W; 101 | 102 | if (!Initialize()) 103 | { 104 | PRINT(_T("Initialize Failed!!!\n")); 105 | return; 106 | } 107 | 108 | InitializeListHead(&head); 109 | //HANDLE SectionHandle = NULL; 110 | __try 111 | { 112 | HANDLE ThreadHandle; 113 | NTSTATUS status = ZwCreateSection(&SectionHandle, 114 | SECTION_MAP_READ | SECTION_MAP_WRITE, 115 | NULL, //backed by the pagefile 116 | &SectionSize, 117 | PAGE_READWRITE, 118 | SEC_COMMIT, 119 | NULL); 120 | 121 | if (!NT_SUCCESS(status)) 122 | { 123 | PRINT(_T("ZwCreateSection error 0x%08lX\n"),status); 124 | __leave; 125 | } 126 | 127 | RtlInitUnicodeString(&usPortName,(PCWSTR)LpcPortName); 128 | InitializeObjectAttributes(&obj,&usPortName,0,NULL,NULL); 129 | 130 | //NtCreatePort checks whether (MaxConnectionInfoLength <= 0x104) and (MaxMessageLength <= 0x148). 131 | status = NtCreatePort(&hConnectPort,&obj,0x104,sizeof(PORT_MESSAGE) + MAX_LPC_DATA,0); 132 | 133 | if (!NT_SUCCESS(status)) 134 | { 135 | PRINT(_T("NtCreatePort error 0x%08lX\n"),status); 136 | __leave; 137 | } 138 | 139 | si.LPCPortHandle = hConnectPort; 140 | si.SectionHandle = SectionHandle; 141 | KeepRunning = TRUE; 142 | 143 | #ifndef _KERNEL_MODE 144 | ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&ServerProc,(LPVOID)&si,0,NULL); 145 | if (ThreadHandle == NULL) 146 | { 147 | PRINT(_T("CreateThread ServerProc error:%d\n"),GetLastError()); 148 | __leave; 149 | } 150 | #else 151 | status = PsCreateSystemThread(&ThreadHandle,0,NULL,NULL,NULL,(PKSTART_ROUTINE)&ServerProc,(PVOID)&si); 152 | if (!NT_SUCCESS(status)) 153 | { 154 | PRINT("PsCreateSystemThread Error:0x%X\n",status); 155 | __leave; 156 | } 157 | #endif 158 | si.ServerThreadHandle = ThreadHandle; 159 | PRINT(_T("Listening to Port \"%ws\",wait for connect...\n"),LpcPortName); 160 | } 161 | __finally 162 | { 163 | 164 | } 165 | } 166 | 167 | void ServerProc(SERVER_INFO *si) 168 | { 169 | HANDLE ConnectionHandle = si->LPCPortHandle; 170 | //PORT_MESSAGE *MessageHeader = (PORT_MESSAGE *)MALLOC(sizeof(PORT_MESSAGE)); 171 | PTRANSFERRED_MESSAGE LPCMessage = (PTRANSFERRED_MESSAGE)MALLOC(sizeof(TRANSFERRED_MESSAGE)); 172 | PORT_MESSAGE *MessageHeader = &LPCMessage->Header; 173 | NTSTATUS status; 174 | ULONG count = 0; 175 | PORT_VIEW ServerView; 176 | HANDLE DataPortHandle = NULL; 177 | REMOTE_PORT_VIEW ClientView; 178 | BOOL isExist = TRUE; 179 | HANDLE ClientHandle = NULL; 180 | CLIENT_ENTRY *ConnectedClient = NULL; 181 | 182 | RtlZeroMemory(LPCMessage,sizeof(TRANSFERRED_MESSAGE)); 183 | 184 | // 185 | // Fill local and remote memory views. When the LPC 186 | // message comes to the client, the section will be remapped 187 | // to be accessible to the listener, even if the client is in another 188 | // process or different processor mode (UserMode/KernelMode) 189 | // 190 | ServerView.Length = sizeof(PORT_VIEW); 191 | ServerView.SectionHandle = si->SectionHandle; 192 | ServerView.SectionOffset = 0; 193 | ServerView.ViewSize = LARGE_MESSAGE_SIZE; 194 | si->ServerView = ServerView; 195 | ClientView.Length = sizeof(REMOTE_PORT_VIEW); 196 | 197 | while (KeepRunning) 198 | { 199 | LIST_ENTRY *pEntry = (&head)->Flink; 200 | TCHAR *buffer; 201 | status = NtReplyWaitReceivePort(ConnectionHandle,(PULONG)&ClientHandle,NULL,MessageHeader); 202 | 203 | if (!NT_SUCCESS(status)) 204 | { 205 | PRINT(_T("NtReplyWaitReceivePort error 0x%08lX\n"),status); 206 | break; 207 | } 208 | 209 | isExist = FALSE; 210 | while (pEntry != &head) 211 | { 212 | CLIENT_ENTRY *info = CONTAINING_RECORD(pEntry,CLIENT_ENTRY,List); 213 | if (info->ClientHandle == ClientHandle) 214 | { 215 | isExist = TRUE; 216 | ConnectedClient = info; 217 | break; 218 | } 219 | pEntry = pEntry->Flink; 220 | } 221 | 222 | if (MessageHeader->u2.s2.Type == LPC_CONNECTION_REQUEST) 223 | { 224 | CLIENT_ENTRY *ce; 225 | if (isExist) 226 | { 227 | PRINT(_T("client [%08lX] message type error!\n"),ClientHandle); 228 | continue; 229 | } 230 | 231 | //status = NtAcceptConnectPort(&DataPortHandle,NULL,MessageHeader,TRUE,&ServerView,&ClientView); 232 | status = NtAcceptConnectPort(&DataPortHandle,NULL,MessageHeader,TRUE,NULL,&ClientView); // win 7 233 | 234 | if (!NT_SUCCESS(status)) 235 | { 236 | PRINT(_T("NtAcceptConnectPort error 0x%08lX\n"),status); 237 | break; 238 | } 239 | 240 | status = NtCompleteConnectPort(DataPortHandle); 241 | if (!NT_SUCCESS(status)) 242 | { 243 | PRINT(_T("NtCompleteConnectPort error 0x%08lX\n"),status); 244 | break; 245 | } 246 | 247 | ce = (CLIENT_ENTRY *)MALLOC(sizeof(CLIENT_ENTRY)); 248 | ce->ClientHandle = DataPortHandle; 249 | ce->ClientView = ClientView; 250 | InsertHeadList(&head,&ce->List); 251 | PRINT(_T("client [%08lX] connected,wait for message...\n"),DataPortHandle); 252 | 253 | continue; 254 | } 255 | else if (MessageHeader->u2.s2.Type == LPC_PORT_CLOSED) 256 | { 257 | RemoveEntryList(&ConnectedClient->List); 258 | PRINT(_T("client [%08lX] die...\n"),ClientHandle); 259 | continue; 260 | } 261 | 262 | //normal message handle 263 | if (!isExist) 264 | { 265 | PRINT(_T("Maybe Server Shutdown Request..\n")); 266 | continue; 267 | } 268 | 269 | LPCMessage = (PTRANSFERRED_MESSAGE)MessageHeader; 270 | if (IS_COMMAND_RESERVE(LPCMessage->Command)) 271 | { 272 | TRANSFERRED_MESSAGE replayMsg; 273 | switch (LPCMessage->Command) 274 | { 275 | case LPC_COMMAND_REQUEST_NOREPLY: 276 | break; 277 | case LPC_COMMAND_REQUEST_REPLY: 278 | RtlCopyMemory(&replayMsg,LPCMessage,sizeof(TRANSFERRED_MESSAGE)); 279 | STRCOPY(replayMsg.MessageText,_T("Server Answer!")); 280 | status = NtReplyPort(ClientHandle,&replayMsg.Header); 281 | if (!NT_SUCCESS(status)) 282 | PRINT(_T("Reply Error: 0x%08lX\n"),status); 283 | break; 284 | case LPC_COMMAND_STOP: 285 | PRINT(_T("[%08lX] Shutdown the Server! We die ...\n"),ClientHandle); 286 | KeepRunning = FALSE; 287 | break; 288 | default: 289 | break; 290 | } 291 | } 292 | else 293 | { 294 | #ifndef _KERNEL_MODE 295 | MAP::iterator iter; 296 | HANDLE hThread; 297 | iter = CallBackList.find(GET_COMMAND(LPCMessage->Command)); 298 | if (iter == CallBackList.end()) 299 | PRINT(_T("Can't find callback function using %d\n"),LPCMessage->Command); 300 | else 301 | { 302 | hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)iter->second,LPCMessage->MessageText,0,0); 303 | if (hThread == INVALID_HANDLE_VALUE) 304 | PRINT(_T("call callback function failed %d\n"),GetLastError()); 305 | if (!IS_COMMAND_ASYNC(LPCMessage->Command)) 306 | { 307 | WaitForSingleObject(hThread,INFINITE); 308 | 309 | TRANSFERRED_MESSAGE replayMsg; 310 | RtlCopyMemory(&replayMsg,LPCMessage,sizeof(TRANSFERRED_MESSAGE)); 311 | STRCOPY(replayMsg.MessageText,L"Server Answer!"); 312 | status = NtReplyPort(ClientHandle,&replayMsg.Header); 313 | if (!NT_SUCCESS(status)) 314 | PRINT(_T("Reply Error: 0x%08lX\n"),status); 315 | } 316 | } 317 | #else 318 | // to do .. 319 | ULONG command = GET_COMMAND(LPCMessage->Command); 320 | PVOID callback = FindCallBack(command); 321 | if (callback) 322 | { 323 | HANDLE tHandle; 324 | status = PsCreateSystemThread(&tHandle,0,NULL,NULL,NULL,(PKSTART_ROUTINE)callback,LPCMessage->MessageText); 325 | if (!NT_SUCCESS(status)) 326 | PRINT(_T("call callback function failed %d\n"),status); 327 | if (!IS_COMMAND_ASYNC(LPCMessage->Command)) 328 | { 329 | TRANSFERRED_MESSAGE replayMsg; 330 | ZwWaitForSingleObject(tHandle,FALSE,NULL); 331 | 332 | RtlCopyMemory(&replayMsg,LPCMessage,sizeof(TRANSFERRED_MESSAGE)); 333 | STRCOPY(replayMsg.MessageText,L"Server Answer!"); 334 | status = NtReplyPort(ClientHandle,&replayMsg.Header); 335 | if (!NT_SUCCESS(status)) 336 | PRINT(_T("Reply Error: 0x%08lX\n"),status); 337 | 338 | } 339 | 340 | ZwClose(tHandle); 341 | } 342 | else 343 | PRINT(_T("Can't find callback function using %d\n"),LPCMessage->Command); 344 | #endif 345 | } 346 | 347 | buffer = (TCHAR *)MALLOC(sizeof(TCHAR)*LARGE_MESSAGE_SIZE); 348 | if (LPCMessage->UseSection) 349 | { 350 | PRINT(_T("[Received Large Data]\n")); 351 | RtlCopyMemory(buffer,ConnectedClient->ClientView.ViewBase,ConnectedClient->ClientView.ViewSize); 352 | PRINT(_T("[%08lX]:%ws\n"),ClientHandle,buffer); 353 | } 354 | else 355 | { 356 | RtlCopyMemory(buffer,LPCMessage->MessageText,MAX_MESSAGE_SIZE); 357 | PRINT(_T("[%08lX]:%ws\n"),ClientHandle,buffer); 358 | } 359 | 360 | FREE(buffer); 361 | } //end of while 362 | 363 | FREE(LPCMessage); 364 | 365 | #ifdef _KERNEL_MODE 366 | NtClose(ConnectionHandle); 367 | PsTerminateSystemThread(STATUS_SUCCESS); 368 | #else 369 | CloseHandle(ConnectionHandle); 370 | #endif 371 | 372 | } 373 | 374 | #ifdef _KERNEL_MODE 375 | BOOL KillThread(PETHREAD Thread); 376 | 377 | void StopServer(TCHAR *ServerName) 378 | { 379 | /*NTSTATUS status; 380 | PETHREAD Thread; 381 | 382 | KeepRunning = FALSE; 383 | status = ObReferenceObjectByHandle(si.ServerThreadHandle,THREAD_ALL_ACCESS,*PsThreadType,KernelMode,&Thread,NULL); 384 | if (!NT_SUCCESS(status)) 385 | { 386 | PRINT("ObReferenceObjectByHandle Error:%X\n",status); 387 | return; 388 | } 389 | 390 | if (!KillThread(Thread)) 391 | return; 392 | */ 393 | NTSTATUS status; 394 | PORT_MESSAGE Request; 395 | PORT_MESSAGE IncomingReply; 396 | KeepRunning = FALSE; 397 | InitializeMessageHeader(&Request,sizeof(PORT_MESSAGE),LPC_NEW_MESSAGE); 398 | status = NtRequestWaitReplyPort(si.LPCPortHandle,&Request,&IncomingReply); 399 | if (!NT_SUCCESS(status) && status != STATUS_LPC_REPLY_LOST) 400 | return; 401 | status = ZwWaitForSingleObject(si.ServerThreadHandle,FALSE,NULL); 402 | if (!NT_SUCCESS(status)) 403 | PRINT("ZwWaitForSingleObject Error:%X\n",status); 404 | ZwClose(si.ServerThreadHandle); 405 | 406 | } 407 | #endif // _KERNEL_MODE 408 | 409 | BOOL Connect(TCHAR *LpcPortName) 410 | { 411 | BOOL success = FALSE; 412 | UNICODE_STRING usPortName; 413 | 414 | SECURITY_QUALITY_OF_SERVICE SecurityQos; 415 | REMOTE_PORT_VIEW ServerView; 416 | LARGE_INTEGER SectionSize = {LARGE_MESSAGE_SIZE}; 417 | PORT_VIEW ClientView; 418 | if (!Initialize()) 419 | { 420 | PRINT(_T("Initialize Failed!!!\n")); 421 | return success; 422 | } 423 | 424 | RtlInitUnicodeString(&usPortName,(PCWSTR)LpcPortName); 425 | 426 | __try 427 | { 428 | HANDLE PortHandle = NULL; 429 | NTSTATUS status = ZwCreateSection(&SectionHandle, 430 | SECTION_MAP_READ | SECTION_MAP_WRITE, 431 | NULL, 432 | &SectionSize, 433 | PAGE_READWRITE, 434 | SEC_COMMIT, 435 | NULL); 436 | 437 | if (!NT_SUCCESS(status)) 438 | { 439 | PRINT(_T("NtCreateSection result 0x%08lX\n"),status); 440 | __leave; 441 | } 442 | 443 | // 444 | // Initialize the parameters of LPC port 445 | SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 446 | SecurityQos.ImpersonationLevel = SecurityImpersonation; 447 | SecurityQos.EffectiveOnly = FALSE; 448 | SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 449 | 450 | // 451 | // Fill local and remote memory view. When the LPC 452 | // message comes to the listener, the section will be remapped 453 | // to be accessible to the listener, even if the listener is in another 454 | // process or different processor mode (UserMode/KernelMode) 455 | // 456 | 457 | ClientView.Length = sizeof(PORT_VIEW); 458 | ClientView.SectionHandle = SectionHandle; 459 | ClientView.SectionOffset = 0; 460 | ClientView.ViewSize = LARGE_MESSAGE_SIZE; 461 | ServerView.Length = sizeof(REMOTE_PORT_VIEW); 462 | 463 | // 464 | // Connect to the port 465 | // 466 | 467 | PRINT(_T("Connecting to port \"%s\" (NtConnectPort)...\n"),LpcPortName); 468 | status = NtConnectPort(&PortHandle, 469 | &usPortName, 470 | &SecurityQos, 471 | &ClientView, 472 | &ServerView, 473 | 0, 474 | NULL, 475 | NULL); 476 | 477 | if (!NT_SUCCESS(status)) 478 | { 479 | PRINT(_T("NtConnectPort error 0x%08lX\n"),status); 480 | __leave; 481 | } 482 | 483 | PRINT(_T("Connect success to %s\n"),LpcPortName); 484 | ci.ClientView = ClientView; 485 | ci.ServerView = ServerView; 486 | ci.ServerHandle = PortHandle; 487 | 488 | success = TRUE; 489 | } 490 | __finally 491 | { 492 | 493 | } 494 | 495 | return success; 496 | } 497 | 498 | 499 | BOOL AsyncSend(TCHAR *msg) 500 | { 501 | return Send(msg,LPC_COMMAND_REQUEST_NOREPLY); 502 | } 503 | 504 | BOOL SyncSend(TCHAR *msg) 505 | { 506 | return Send(msg,LPC_COMMAND_REQUEST_REPLY); 507 | } 508 | 509 | BOOL Send(TCHAR *msg,ULONG command) 510 | { 511 | TRANSFERRED_MESSAGE Message; 512 | NTSTATUS status; 513 | ULONG MessageLength = sizeof(TRANSFERRED_MESSAGE); 514 | SIZE_T dataSize = (STRLEN(msg)+1)*sizeof(TCHAR); 515 | 516 | RtlZeroMemory(&Message,MessageLength); 517 | InitializeMessageHeader(&Message.Header,MessageLength,LPC_NEW_MESSAGE); 518 | Message.Command = command; 519 | 520 | if (dataSize > MAX_MESSAGE_SIZE) 521 | { 522 | if (dataSize > LARGE_MESSAGE_SIZE) 523 | return FALSE; 524 | //write to section 525 | Message.UseSection = TRUE; 526 | STRCOPY(Message.MessageText,_T("Real Message is in the Section!")); 527 | RtlCopyMemory(ci.ClientView.ViewBase,msg,dataSize); 528 | 529 | } 530 | else 531 | { 532 | //write to buffer of message 533 | Message.UseSection = FALSE; 534 | RtlCopyMemory(Message.MessageText,msg,dataSize); 535 | } 536 | 537 | if (IS_COMMAND_ASYNC(command)) 538 | { 539 | // 540 | // Send the data request, do not wait for reply 541 | // 542 | 543 | /* 544 | * Attention! 545 | * LPC_REQUEST type will cause STATUS_INVALID_PARAMETER when use NtRequestPort 546 | */ 547 | status = NtRequestPort(ci.ServerHandle, &Message.Header); 548 | 549 | if (!NT_SUCCESS(status)) 550 | { 551 | PRINT(_T("NtRequestPort error 0x%08lX\n"), status); 552 | } 553 | } 554 | else 555 | { 556 | // 557 | // Send the data request, and wait for reply 558 | // 559 | TRANSFERRED_MESSAGE ReplyMessage; 560 | TCHAR *buffer; 561 | RtlZeroMemory(&ReplyMessage,MessageLength); 562 | InitializeMessageHeader(&ReplyMessage.Header,MessageLength,LPC_REPLY); 563 | status = NtRequestWaitReplyPort(ci.ServerHandle, &Message.Header,&ReplyMessage.Header); 564 | 565 | if (!NT_SUCCESS(status)) 566 | { 567 | PRINT(_T("NtRequestPort error 0x%08lX\n"), status); 568 | } 569 | else 570 | { 571 | buffer = (TCHAR *)MALLOC(sizeof(TCHAR)*LARGE_MESSAGE_SIZE); 572 | if (ReplyMessage.UseSection) 573 | { 574 | PRINT(_T("[Received Large Data]\n")); 575 | RtlCopyMemory(buffer,ci.ServerView.ViewBase,ci.ServerView.ViewSize); 576 | PRINT(_T("[%08lX]:%ws\n"),ci.ServerHandle,buffer); 577 | } 578 | else 579 | { 580 | RtlCopyMemory(buffer,ReplyMessage.MessageText,sizeof(ReplyMessage.MessageText)); 581 | PRINT(_T("[%08lX]:%ws\n"),ci.ServerHandle,buffer); 582 | } 583 | 584 | FREE(buffer); 585 | } 586 | } 587 | 588 | return NT_SUCCESS(status); 589 | } 590 | 591 | #ifndef _KERNEL_MODE 592 | BOOL InitProcAddress() 593 | { 594 | HMODULE hModule = GetModuleHandle(L"ntdll.dll"); 595 | if (hModule != NULL) 596 | { 597 | NtCreatePort = (_CreatePort)GetProcAddress(hModule,"NtCreatePort"); 598 | NtListenPort = (_ListenPort)GetProcAddress(hModule,"NtListenPort"); 599 | NtAcceptConnectPort = (_AcceptConnectPort)GetProcAddress(hModule,"NtAcceptConnectPort"); 600 | NtCompleteConnectPort = (_CompleteConnectPort)GetProcAddress (hModule,"NtCompleteConnectPort"); 601 | NtReplyPort = (_ReplyPort )GetProcAddress(hModule,"NtReplyPort"); 602 | NtReplyWaitReceivePort = (_ReplyWaitReceivePort)GetProcAddress (hModule,"NtReplyWaitReceivePort"); 603 | NtReplyWaitReceivePortEx = (_ReplyWaitReceivePortEx)GetProcAddress(hModule,"NtReplyWaitReceivePortEx"); 604 | RtlInitUnicodeString = (_InitUnicodeString)GetProcAddress(hModule,"RtlInitUnicodeString"); 605 | NtConnectPort = (_ConnectPort)GetProcAddress(hModule,"NtConnectPort"); 606 | ZwCreateSection = (_ZwCreateSection)GetProcAddress(hModule,"ZwCreateSection"); 607 | NtRequestPort = (_RequestPort)GetProcAddress(hModule,"NtRequestPort"); 608 | NtRequestWaitReplyPort = (_RequestWaitReplyPort)GetProcAddress(hModule,"NtRequestWaitReplyPort"); 609 | 610 | if (NtCreatePort && NtListenPort && NtAcceptConnectPort && NtCompleteConnectPort && NtReplyPort && NtRequestWaitReplyPort && 611 | NtReplyWaitReceivePort && NtReplyWaitReceivePortEx && RtlInitUnicodeString && NtConnectPort && ZwCreateSection && NtRequestPort) 612 | return TRUE; 613 | } 614 | 615 | return FALSE; 616 | } 617 | 618 | BOOL CheckWOW64() 619 | { 620 | BOOL isUnderWOW64; 621 | if (IsWow64Process(GetCurrentProcess(),&isUnderWOW64)) 622 | { 623 | if (isUnderWOW64) 624 | { 625 | PRINT(_T("WARNING: You are running 32-bit version of the application under 64-bit Windows.\n") 626 | _T("This is not supported and will not work.\n")); 627 | return TRUE; 628 | } 629 | } 630 | return FALSE; 631 | }; 632 | #else 633 | ULONG GetSystemRoutineAddress(int,PVOID); 634 | DWORD GetFunctionAddressBySSDT(DWORD,WCHAR *); 635 | 636 | BOOL FindKernelFunction() 637 | { 638 | NtConnectPort = (_ConnectPort)GetSystemRoutineAddress(0,"NtConnectPort"); 639 | NtCreatePort = (_CreatePort)GetFunctionAddressBySSDT(0,L"NtCreatePort"); 640 | NtListenPort = (_ListenPort)GetFunctionAddressBySSDT(0,L"NtListenPort"); 641 | NtAcceptConnectPort = (_AcceptConnectPort)GetFunctionAddressBySSDT(0,L"NtAcceptConnectPort"); 642 | NtCompleteConnectPort = (_CompleteConnectPort)GetFunctionAddressBySSDT(0,L"NtCompleteConnectPort"); 643 | NtReplyPort = (_ReplyPort)GetFunctionAddressBySSDT(0,L"NtReplyPort"); 644 | NtReplyWaitReceivePort = (_ReplyWaitReceivePort)GetFunctionAddressBySSDT(0,L"NtReplyWaitReceivePort"); 645 | NtReplyWaitReceivePortEx = (_ReplyWaitReceivePortEx)GetFunctionAddressBySSDT(0,L"NtReplyWaitReceivePortEx"); 646 | NtRequestPort = (_RequestPort)GetFunctionAddressBySSDT(0,L"NtRequestPort"); 647 | NtRequestWaitReplyPort = (_RequestWaitReplyPort)GetFunctionAddressBySSDT(0,L"NtRequestWaitReplyPort"); 648 | 649 | if (NtCreatePort && NtListenPort && NtAcceptConnectPort && NtCompleteConnectPort && NtReplyPort && NtRequestWaitReplyPort && 650 | NtReplyWaitReceivePort && NtReplyWaitReceivePortEx && NtRequestPort && NtRequestWaitReplyPort && NtConnectPort) 651 | return TRUE; 652 | 653 | return FALSE; 654 | } 655 | #endif 656 | 657 | void Control( ULONG command,ULONG method, TCHAR *msg ) 658 | { 659 | SET_COMMAND(command,method); 660 | Send(msg,command); 661 | } 662 | -------------------------------------------------------------------------------- /inc/utlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef UTLIST_H 25 | #define UTLIST_H 26 | 27 | #define UTLIST_VERSION 1.9.8 28 | 29 | #include 30 | 31 | /* 32 | * This file contains macros to manipulate singly and doubly-linked lists. 33 | * 34 | * 1. LL_ macros: singly-linked lists. 35 | * 2. DL_ macros: doubly-linked lists. 36 | * 3. CDL_ macros: circular doubly-linked lists. 37 | * 38 | * To use singly-linked lists, your structure must have a "next" pointer. 39 | * To use doubly-linked lists, your structure must "prev" and "next" pointers. 40 | * Either way, the pointer to the head of the list must be initialized to NULL. 41 | * 42 | * ----------------.EXAMPLE ------------------------- 43 | * struct item { 44 | * int id; 45 | * struct item *prev, *next; 46 | * } 47 | * 48 | * struct item *list = NULL: 49 | * 50 | * int main() { 51 | * struct item *item; 52 | * ... allocate and populate item ... 53 | * DL_APPEND(list, item); 54 | * } 55 | * -------------------------------------------------- 56 | * 57 | * For doubly-linked lists, the append and delete macros are O(1) 58 | * For singly-linked lists, append and delete are O(n) but prepend is O(1) 59 | * The sort macro is O(n log(n)) for all types of single/double/circular lists. 60 | */ 61 | 62 | /* These macros use decltype or the earlier __typeof GNU extension. 63 | As decltype is only available in newer compilers (VS2010 or gcc 4.3+ 64 | when compiling c++ code), this code uses whatever method is needed 65 | or, for VS2008 where neither is available, uses casting workarounds. */ 66 | #ifdef _MSC_VER /* MS compiler */ 67 | #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ 68 | #define LDECLTYPE(x) decltype(x) 69 | #else /* VS2008 or older (or VS2010 in C mode) */ 70 | #define NO_DECLTYPE 71 | #define LDECLTYPE(x) char* 72 | #endif 73 | #elif defined(__ICCARM__) 74 | #define NO_DECLTYPE 75 | #define LDECLTYPE(x) char* 76 | #else /* GNU, Sun and other compilers */ 77 | #define LDECLTYPE(x) __typeof(x) 78 | #endif 79 | 80 | /* for VS2008 we use some workarounds to get around the lack of decltype, 81 | * namely, we always reassign our tmp variable to the list head if we need 82 | * to dereference its prev/next pointers, and save/restore the real head.*/ 83 | #ifdef NO_DECLTYPE 84 | #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } 85 | #define _NEXT(elt,list,next) ((char*)((list)->next)) 86 | #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } 87 | /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */ 88 | #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } 89 | #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } 90 | #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } 91 | #else 92 | #define _SV(elt,list) 93 | #define _NEXT(elt,list,next) ((elt)->next) 94 | #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to) 95 | /* #define _PREV(elt,list,prev) ((elt)->prev) */ 96 | #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) 97 | #define _RS(list) 98 | #define _CASTASGN(a,b) (a)=(b) 99 | #endif 100 | 101 | /****************************************************************************** 102 | * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * 103 | * Unwieldy variable names used here to avoid shadowing passed-in variables. * 104 | *****************************************************************************/ 105 | #define LL_SORT(list, cmp) \ 106 | LL_SORT2(list, cmp, next) 107 | 108 | #define LL_SORT2(list, cmp, next) \ 109 | do { \ 110 | LDECLTYPE(list) _ls_p; \ 111 | LDECLTYPE(list) _ls_q; \ 112 | LDECLTYPE(list) _ls_e; \ 113 | LDECLTYPE(list) _ls_tail; \ 114 | int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ 115 | if (list) { \ 116 | _ls_insize = 1; \ 117 | _ls_looping = 1; \ 118 | while (_ls_looping) { \ 119 | _CASTASGN(_ls_p,list); \ 120 | list = NULL; \ 121 | _ls_tail = NULL; \ 122 | _ls_nmerges = 0; \ 123 | while (_ls_p) { \ 124 | _ls_nmerges++; \ 125 | _ls_q = _ls_p; \ 126 | _ls_psize = 0; \ 127 | for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ 128 | _ls_psize++; \ 129 | _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ 130 | if (!_ls_q) break; \ 131 | } \ 132 | _ls_qsize = _ls_insize; \ 133 | while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ 134 | if (_ls_psize == 0) { \ 135 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 136 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 137 | } else if (_ls_qsize == 0 || !_ls_q) { \ 138 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 139 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 140 | } else if (cmp(_ls_p,_ls_q) <= 0) { \ 141 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 142 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 143 | } else { \ 144 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 145 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 146 | } \ 147 | if (_ls_tail) { \ 148 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ 149 | } else { \ 150 | _CASTASGN(list,_ls_e); \ 151 | } \ 152 | _ls_tail = _ls_e; \ 153 | } \ 154 | _ls_p = _ls_q; \ 155 | } \ 156 | if (_ls_tail) { \ 157 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ 158 | } \ 159 | if (_ls_nmerges <= 1) { \ 160 | _ls_looping=0; \ 161 | } \ 162 | _ls_insize *= 2; \ 163 | } \ 164 | } \ 165 | } while (0) 166 | 167 | 168 | #define DL_SORT(list, cmp) \ 169 | DL_SORT2(list, cmp, prev, next) 170 | 171 | #define DL_SORT2(list, cmp, prev, next) \ 172 | do { \ 173 | LDECLTYPE(list) _ls_p; \ 174 | LDECLTYPE(list) _ls_q; \ 175 | LDECLTYPE(list) _ls_e; \ 176 | LDECLTYPE(list) _ls_tail; \ 177 | int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ 178 | if (list) { \ 179 | _ls_insize = 1; \ 180 | _ls_looping = 1; \ 181 | while (_ls_looping) { \ 182 | _CASTASGN(_ls_p,list); \ 183 | list = NULL; \ 184 | _ls_tail = NULL; \ 185 | _ls_nmerges = 0; \ 186 | while (_ls_p) { \ 187 | _ls_nmerges++; \ 188 | _ls_q = _ls_p; \ 189 | _ls_psize = 0; \ 190 | for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ 191 | _ls_psize++; \ 192 | _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \ 193 | if (!_ls_q) break; \ 194 | } \ 195 | _ls_qsize = _ls_insize; \ 196 | while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ 197 | if (_ls_psize == 0) { \ 198 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 199 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 200 | } else if (_ls_qsize == 0 || !_ls_q) { \ 201 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 202 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 203 | } else if (cmp(_ls_p,_ls_q) <= 0) { \ 204 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 205 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 206 | } else { \ 207 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 208 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 209 | } \ 210 | if (_ls_tail) { \ 211 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ 212 | } else { \ 213 | _CASTASGN(list,_ls_e); \ 214 | } \ 215 | _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ 216 | _ls_tail = _ls_e; \ 217 | } \ 218 | _ls_p = _ls_q; \ 219 | } \ 220 | _CASTASGN(list->prev, _ls_tail); \ 221 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ 222 | if (_ls_nmerges <= 1) { \ 223 | _ls_looping=0; \ 224 | } \ 225 | _ls_insize *= 2; \ 226 | } \ 227 | } \ 228 | } while (0) 229 | 230 | #define CDL_SORT(list, cmp) \ 231 | CDL_SORT2(list, cmp, prev, next) 232 | 233 | #define CDL_SORT2(list, cmp, prev, next) \ 234 | do { \ 235 | LDECLTYPE(list) _ls_p; \ 236 | LDECLTYPE(list) _ls_q; \ 237 | LDECLTYPE(list) _ls_e; \ 238 | LDECLTYPE(list) _ls_tail; \ 239 | LDECLTYPE(list) _ls_oldhead; \ 240 | LDECLTYPE(list) _tmp; \ 241 | int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ 242 | if (list) { \ 243 | _ls_insize = 1; \ 244 | _ls_looping = 1; \ 245 | while (_ls_looping) { \ 246 | _CASTASGN(_ls_p,list); \ 247 | _CASTASGN(_ls_oldhead,list); \ 248 | list = NULL; \ 249 | _ls_tail = NULL; \ 250 | _ls_nmerges = 0; \ 251 | while (_ls_p) { \ 252 | _ls_nmerges++; \ 253 | _ls_q = _ls_p; \ 254 | _ls_psize = 0; \ 255 | for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ 256 | _ls_psize++; \ 257 | _SV(_ls_q,list); \ 258 | if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \ 259 | _ls_q = NULL; \ 260 | } else { \ 261 | _ls_q = _NEXT(_ls_q,list,next); \ 262 | } \ 263 | _RS(list); \ 264 | if (!_ls_q) break; \ 265 | } \ 266 | _ls_qsize = _ls_insize; \ 267 | while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ 268 | if (_ls_psize == 0) { \ 269 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 270 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 271 | if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ 272 | } else if (_ls_qsize == 0 || !_ls_q) { \ 273 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 274 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 275 | if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ 276 | } else if (cmp(_ls_p,_ls_q) <= 0) { \ 277 | _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \ 278 | _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \ 279 | if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ 280 | } else { \ 281 | _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ 282 | _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ 283 | if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ 284 | } \ 285 | if (_ls_tail) { \ 286 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ 287 | } else { \ 288 | _CASTASGN(list,_ls_e); \ 289 | } \ 290 | _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ 291 | _ls_tail = _ls_e; \ 292 | } \ 293 | _ls_p = _ls_q; \ 294 | } \ 295 | _CASTASGN(list->prev,_ls_tail); \ 296 | _CASTASGN(_tmp,list); \ 297 | _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \ 298 | if (_ls_nmerges <= 1) { \ 299 | _ls_looping=0; \ 300 | } \ 301 | _ls_insize *= 2; \ 302 | } \ 303 | } \ 304 | } while (0) 305 | 306 | /****************************************************************************** 307 | * singly linked list macros (non-circular) * 308 | *****************************************************************************/ 309 | #define LL_PREPEND(head,add) \ 310 | LL_PREPEND2(head,add,next) 311 | 312 | #define LL_PREPEND2(head,add,next) \ 313 | do { \ 314 | (add)->next = head; \ 315 | head = add; \ 316 | } while (0) 317 | 318 | #define LL_CONCAT(head1,head2) \ 319 | LL_CONCAT2(head1,head2,next) 320 | 321 | #define LL_CONCAT2(head1,head2,next) \ 322 | do { \ 323 | LDECLTYPE(head1) _tmp; \ 324 | if (head1) { \ 325 | _tmp = head1; \ 326 | while (_tmp->next) { _tmp = _tmp->next; } \ 327 | _tmp->next=(head2); \ 328 | } else { \ 329 | (head1)=(head2); \ 330 | } \ 331 | } while (0) 332 | 333 | #define LL_APPEND(head,add) \ 334 | LL_APPEND2(head,add,next) 335 | 336 | #define LL_APPEND2(head,add,next) \ 337 | do { \ 338 | LDECLTYPE(head) _tmp; \ 339 | (add)->next=NULL; \ 340 | if (head) { \ 341 | _tmp = head; \ 342 | while (_tmp->next) { _tmp = _tmp->next; } \ 343 | _tmp->next=(add); \ 344 | } else { \ 345 | (head)=(add); \ 346 | } \ 347 | } while (0) 348 | 349 | #define LL_DELETE(head,del) \ 350 | LL_DELETE2(head,del,next) 351 | 352 | #define LL_DELETE2(head,del,next) \ 353 | do { \ 354 | LDECLTYPE(head) _tmp; \ 355 | if ((head) == (del)) { \ 356 | (head)=(head)->next; \ 357 | } else { \ 358 | _tmp = head; \ 359 | while (_tmp->next && (_tmp->next != (del))) { \ 360 | _tmp = _tmp->next; \ 361 | } \ 362 | if (_tmp->next) { \ 363 | _tmp->next = ((del)->next); \ 364 | } \ 365 | } \ 366 | } while (0) 367 | 368 | /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ 369 | #define LL_APPEND_VS2008(head,add) \ 370 | LL_APPEND2_VS2008(head,add,next) 371 | 372 | #define LL_APPEND2_VS2008(head,add,next) \ 373 | do { \ 374 | if (head) { \ 375 | (add)->next = head; /* use add->next as a temp variable */ \ 376 | while ((add)->next->next) { (add)->next = (add)->next->next; } \ 377 | (add)->next->next=(add); \ 378 | } else { \ 379 | (head)=(add); \ 380 | } \ 381 | (add)->next=NULL; \ 382 | } while (0) 383 | 384 | #define LL_DELETE_VS2008(head,del) \ 385 | LL_DELETE2_VS2008(head,del,next) 386 | 387 | #define LL_DELETE2_VS2008(head,del,next) \ 388 | do { \ 389 | if ((head) == (del)) { \ 390 | (head)=(head)->next; \ 391 | } else { \ 392 | char *_tmp = (char*)(head); \ 393 | while ((head)->next && ((head)->next != (del))) { \ 394 | head = (head)->next; \ 395 | } \ 396 | if ((head)->next) { \ 397 | (head)->next = ((del)->next); \ 398 | } \ 399 | { \ 400 | char **_head_alias = (char**)&(head); \ 401 | *_head_alias = _tmp; \ 402 | } \ 403 | } \ 404 | } while (0) 405 | #ifdef NO_DECLTYPE 406 | #undef LL_APPEND 407 | #define LL_APPEND LL_APPEND_VS2008 408 | #undef LL_DELETE 409 | #define LL_DELETE LL_DELETE_VS2008 410 | #undef LL_DELETE2 411 | #define LL_DELETE2 LL_DELETE2_VS2008 412 | #undef LL_APPEND2 413 | #define LL_APPEND2 LL_APPEND2_VS2008 414 | #undef LL_CONCAT /* no LL_CONCAT_VS2008 */ 415 | #undef DL_CONCAT /* no DL_CONCAT_VS2008 */ 416 | #endif 417 | /* end VS2008 replacements */ 418 | 419 | #define LL_FOREACH(head,el) \ 420 | LL_FOREACH2(head,el,next) 421 | 422 | #define LL_FOREACH2(head,el,next) \ 423 | for(el=head;el;el=(el)->next) 424 | 425 | #define LL_FOREACH_SAFE(head,el,tmp) \ 426 | LL_FOREACH_SAFE2(head,el,tmp,next) 427 | 428 | #define LL_FOREACH_SAFE2(head,el,tmp,next) \ 429 | for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) 430 | 431 | #define LL_SEARCH_SCALAR(head,out,field,val) \ 432 | LL_SEARCH_SCALAR2(head,out,field,val,next) 433 | 434 | #define LL_SEARCH_SCALAR2(head,out,field,val,next) \ 435 | do { \ 436 | LL_FOREACH2(head,out,next) { \ 437 | if ((out)->field == (val)) break; \ 438 | } \ 439 | } while(0) 440 | 441 | #define LL_SEARCH(head,out,elt,cmp) \ 442 | LL_SEARCH2(head,out,elt,cmp,next) 443 | 444 | #define LL_SEARCH2(head,out,elt,cmp,next) \ 445 | do { \ 446 | LL_FOREACH2(head,out,next) { \ 447 | if ((cmp(out,elt))==0) break; \ 448 | } \ 449 | } while(0) 450 | 451 | #define LL_REPLACE_ELEM(head, el, add) \ 452 | do { \ 453 | LDECLTYPE(head) _tmp; \ 454 | assert(head != NULL); \ 455 | assert(el != NULL); \ 456 | assert(add != NULL); \ 457 | (add)->next = (el)->next; \ 458 | if ((head) == (el)) { \ 459 | (head) = (add); \ 460 | } else { \ 461 | _tmp = head; \ 462 | while (_tmp->next && (_tmp->next != (el))) { \ 463 | _tmp = _tmp->next; \ 464 | } \ 465 | if (_tmp->next) { \ 466 | _tmp->next = (add); \ 467 | } \ 468 | } \ 469 | } while (0) 470 | 471 | #define LL_PREPEND_ELEM(head, el, add) \ 472 | do { \ 473 | LDECLTYPE(head) _tmp; \ 474 | assert(head != NULL); \ 475 | assert(el != NULL); \ 476 | assert(add != NULL); \ 477 | (add)->next = (el); \ 478 | if ((head) == (el)) { \ 479 | (head) = (add); \ 480 | } else { \ 481 | _tmp = head; \ 482 | while (_tmp->next && (_tmp->next != (el))) { \ 483 | _tmp = _tmp->next; \ 484 | } \ 485 | if (_tmp->next) { \ 486 | _tmp->next = (add); \ 487 | } \ 488 | } \ 489 | } while (0) \ 490 | 491 | 492 | /****************************************************************************** 493 | * doubly linked list macros (non-circular) * 494 | *****************************************************************************/ 495 | #define DL_PREPEND(head,add) \ 496 | DL_PREPEND2(head,add,prev,next) 497 | 498 | #define DL_PREPEND2(head,add,prev,next) \ 499 | do { \ 500 | (add)->next = head; \ 501 | if (head) { \ 502 | (add)->prev = (head)->prev; \ 503 | (head)->prev = (add); \ 504 | } else { \ 505 | (add)->prev = (add); \ 506 | } \ 507 | (head) = (add); \ 508 | } while (0) 509 | 510 | #define DL_APPEND(head,add) \ 511 | DL_APPEND2(head,add,prev,next) 512 | 513 | #define DL_APPEND2(head,add,prev,next) \ 514 | do { \ 515 | if (head) { \ 516 | (add)->prev = (head)->prev; \ 517 | (head)->prev->next = (add); \ 518 | (head)->prev = (add); \ 519 | (add)->next = NULL; \ 520 | } else { \ 521 | (head)=(add); \ 522 | (head)->prev = (head); \ 523 | (head)->next = NULL; \ 524 | } \ 525 | } while (0) 526 | 527 | #define DL_CONCAT(head1,head2) \ 528 | DL_CONCAT2(head1,head2,prev,next) 529 | 530 | #define DL_CONCAT2(head1,head2,prev,next) \ 531 | do { \ 532 | LDECLTYPE(head1) _tmp; \ 533 | if (head2) { \ 534 | if (head1) { \ 535 | _tmp = (head2)->prev; \ 536 | (head2)->prev = (head1)->prev; \ 537 | (head1)->prev->next = (head2); \ 538 | (head1)->prev = _tmp; \ 539 | } else { \ 540 | (head1)=(head2); \ 541 | } \ 542 | } \ 543 | } while (0) 544 | 545 | #define DL_DELETE(head,del) \ 546 | DL_DELETE2(head,del,prev,next) 547 | 548 | #define DL_DELETE2(head,del,prev,next) \ 549 | do { \ 550 | assert((del)->prev != NULL); \ 551 | if ((del)->prev == (del)) { \ 552 | (head)=NULL; \ 553 | } else if ((del)==(head)) { \ 554 | (del)->next->prev = (del)->prev; \ 555 | (head) = (del)->next; \ 556 | } else { \ 557 | (del)->prev->next = (del)->next; \ 558 | if ((del)->next) { \ 559 | (del)->next->prev = (del)->prev; \ 560 | } else { \ 561 | (head)->prev = (del)->prev; \ 562 | } \ 563 | } \ 564 | } while (0) 565 | 566 | 567 | #define DL_FOREACH(head,el) \ 568 | DL_FOREACH2(head,el,next) 569 | 570 | #define DL_FOREACH2(head,el,next) \ 571 | for(el=head;el;el=(el)->next) 572 | 573 | /* this version is safe for deleting the elements during iteration */ 574 | #define DL_FOREACH_SAFE(head,el,tmp) \ 575 | DL_FOREACH_SAFE2(head,el,tmp,next) 576 | 577 | #define DL_FOREACH_SAFE2(head,el,tmp,next) \ 578 | for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) 579 | 580 | /* these are identical to their singly-linked list counterparts */ 581 | #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR 582 | #define DL_SEARCH LL_SEARCH 583 | #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 584 | #define DL_SEARCH2 LL_SEARCH2 585 | 586 | #define DL_REPLACE_ELEM(head, el, add) \ 587 | do { \ 588 | assert(head != NULL); \ 589 | assert(el != NULL); \ 590 | assert(add != NULL); \ 591 | if ((head) == (el)) { \ 592 | (head) = (add); \ 593 | (add)->next = (el)->next; \ 594 | if ((el)->next == NULL) { \ 595 | (add)->prev = (add); \ 596 | } else { \ 597 | (add)->prev = (el)->prev; \ 598 | (add)->next->prev = (add); \ 599 | } \ 600 | } else { \ 601 | (add)->next = (el)->next; \ 602 | (add)->prev = (el)->prev; \ 603 | (add)->prev->next = (add); \ 604 | if ((el)->next == NULL) { \ 605 | (head)->prev = (add); \ 606 | } else { \ 607 | (add)->next->prev = (add); \ 608 | } \ 609 | } \ 610 | } while (0) 611 | 612 | #define DL_PREPEND_ELEM(head, el, add) \ 613 | do { \ 614 | assert(head != NULL); \ 615 | assert(el != NULL); \ 616 | assert(add != NULL); \ 617 | (add)->next = (el); \ 618 | (add)->prev = (el)->prev; \ 619 | (el)->prev = (add); \ 620 | if ((head) == (el)) { \ 621 | (head) = (add); \ 622 | } else { \ 623 | (add)->prev->next = (add); \ 624 | } \ 625 | } while (0) \ 626 | 627 | 628 | /****************************************************************************** 629 | * circular doubly linked list macros * 630 | *****************************************************************************/ 631 | #define CDL_PREPEND(head,add) \ 632 | CDL_PREPEND2(head,add,prev,next) 633 | 634 | #define CDL_PREPEND2(head,add,prev,next) \ 635 | do { \ 636 | if (head) { \ 637 | (add)->prev = (head)->prev; \ 638 | (add)->next = (head); \ 639 | (head)->prev = (add); \ 640 | (add)->prev->next = (add); \ 641 | } else { \ 642 | (add)->prev = (add); \ 643 | (add)->next = (add); \ 644 | } \ 645 | (head)=(add); \ 646 | } while (0) 647 | 648 | #define CDL_DELETE(head,del) \ 649 | CDL_DELETE2(head,del,prev,next) 650 | 651 | #define CDL_DELETE2(head,del,prev,next) \ 652 | do { \ 653 | if ( ((head)==(del)) && ((head)->next == (head))) { \ 654 | (head) = 0L; \ 655 | } else { \ 656 | (del)->next->prev = (del)->prev; \ 657 | (del)->prev->next = (del)->next; \ 658 | if ((del) == (head)) (head)=(del)->next; \ 659 | } \ 660 | } while (0) 661 | 662 | #define CDL_FOREACH(head,el) \ 663 | CDL_FOREACH2(head,el,next) 664 | 665 | #define CDL_FOREACH2(head,el,next) \ 666 | for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) 667 | 668 | #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ 669 | CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) 670 | 671 | #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ 672 | for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ 673 | (el) && ((tmp2)=(el)->next, 1); \ 674 | ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) 675 | 676 | #define CDL_SEARCH_SCALAR(head,out,field,val) \ 677 | CDL_SEARCH_SCALAR2(head,out,field,val,next) 678 | 679 | #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ 680 | do { \ 681 | CDL_FOREACH2(head,out,next) { \ 682 | if ((out)->field == (val)) break; \ 683 | } \ 684 | } while(0) 685 | 686 | #define CDL_SEARCH(head,out,elt,cmp) \ 687 | CDL_SEARCH2(head,out,elt,cmp,next) 688 | 689 | #define CDL_SEARCH2(head,out,elt,cmp,next) \ 690 | do { \ 691 | CDL_FOREACH2(head,out,next) { \ 692 | if ((cmp(out,elt))==0) break; \ 693 | } \ 694 | } while(0) 695 | 696 | #define CDL_REPLACE_ELEM(head, el, add) \ 697 | do { \ 698 | assert(head != NULL); \ 699 | assert(el != NULL); \ 700 | assert(add != NULL); \ 701 | if ((el)->next == (el)) { \ 702 | (add)->next = (add); \ 703 | (add)->prev = (add); \ 704 | (head) = (add); \ 705 | } else { \ 706 | (add)->next = (el)->next; \ 707 | (add)->prev = (el)->prev; \ 708 | (add)->next->prev = (add); \ 709 | (add)->prev->next = (add); \ 710 | if ((head) == (el)) { \ 711 | (head) = (add); \ 712 | } \ 713 | } \ 714 | } while (0) 715 | 716 | #define CDL_PREPEND_ELEM(head, el, add) \ 717 | do { \ 718 | assert(head != NULL); \ 719 | assert(el != NULL); \ 720 | assert(add != NULL); \ 721 | (add)->next = (el); \ 722 | (add)->prev = (el)->prev; \ 723 | (el)->prev = (add); \ 724 | (add)->prev->next = (add); \ 725 | if ((head) == (el)) { \ 726 | (head) = (add); \ 727 | } \ 728 | } while (0) \ 729 | 730 | #endif /* UTLIST_H */ 731 | 732 | --------------------------------------------------------------------------------