/*

   H-CL par 0vercl0k <http://0vercl0k.blogspot.com>

*/

#ifndef _H_C_L
#define _H_C_L

#include <wdm.h>
#include <string.h>

/* Defines utilisées dans les fonctions */

#define WINAPI __stdcall
#define IMAGE_DIRECTORY_ENTRY_EXPORT          0

/*                                      */

/* Compatibilité avec les types windows */

typedef unsigned long DWORD;
typedef DWORD *PDWORD;
typedef unsigned char BYTE;
typedef BYTE *PBYTE;
typedef unsigned short WORD;
typedef int BOOL;

/*                                      */

/* Déclaration / Définition des structures utilisées et autres defines */

typedef struct ServiceDescriptorEntry
{
  PDWORD ServiceTable;
  PDWORD CounterTableBase;
  DWORD ServiceLimit;
  PBYTE ArgumentTable;
} SSDT;

typedef struct _LDR_DATA_TABLE_ENTRY {
  LIST_ENTRY InLoadOrderLinks;
  LIST_ENTRY InMemoryOrderLinks;
  LIST_ENTRY InInitializationOrderLinks;
  PVOID DllBase;
  PVOID EntryPoint;
  ULONG SizeOfImage;
  UNICODE_STRING FullDllName;
  UNICODE_STRING BaseDllName;
  ULONG Flags;
  WORD LoadCount;
  WORD TlsIndex;
  union
  {
    LIST_ENTRY HashLinks;
    struct
    {
        PVOID SectionPointer;
        ULONG CheckSum;
    };
   };
   union
   {
     ULONG TimeDateStamp;
     PVOID LoadedImports;
   };
   PVOID EntryPointActivationContext;
   PVOID PatchInformation;
   LIST_ENTRY ForwarderLinks;
   LIST_ENTRY ServiceTagLinks;
   LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _KEXECUTE_OPTIONS {
  ULONG ExecuteDisable: 1;
  ULONG ExecuteEnable: 1;
  ULONG DisableThunkEmulation: 1;
  ULONG Permanent: 1;
  ULONG ExecuteDispatchEnable: 1;
  ULONG ImageDispatchEnable: 1;
  ULONG Spare: 2;
} KEXECUTE_OPTIONS, *PKEXECUTE_OPTIONS;

typedef struct _KIDTENTRY {
  WORD Offset;
  WORD Selector;
  WORD Access;
  WORD ExtendedOffset;
} KIDTENTRY, *PKIDTENTRY;

typedef struct _KGDTENTRY {
  WORD LimitLow;
  WORD BaseLow;
  ULONG HighWord;
} KGDTENTRY, *PKGDTENTRY;


typedef struct _KPROCESS {
  DISPATCHER_HEADER Header;
  LIST_ENTRY ProfileListHead;
  ULONG DirectoryTableBase;
  ULONG Unused0;
  KGDTENTRY LdtDescriptor;
  KIDTENTRY Int21Descriptor;
  WORD IopmOffset;
  UCHAR Iopl;
  UCHAR Unused;
  ULONG ActiveProcessors;
  ULONG KernelTime;
  ULONG UserTime;
  LIST_ENTRY ReadyListHead;
  SINGLE_LIST_ENTRY SwapListEntry;
  PVOID VdmTrapcHandler;
  LIST_ENTRY ThreadListHead;
  ULONG ProcessLock;
  ULONG Affinity;
  union
  {
    ULONG AutoAlignment: 1;
    ULONG DisableBoost: 1;
    ULONG DisableQuantum: 1;
    ULONG ReservedFlags: 29;
    LONG ProcessFlags;
  };
  CHAR BasePriority;
  CHAR QuantumReset;
  UCHAR State;
  UCHAR ThreadSeed;
  UCHAR PowerState;
  UCHAR IdealNode;
  UCHAR Visited;
  union
  {
    KEXECUTE_OPTIONS Flags;
    UCHAR ExecuteOptions;
  };
  ULONG StackCount;
  LIST_ENTRY ProcessListEntry;
  UINT64 CycleTime;
} KPROCESS, *PKPROCESS;

typedef struct _KAPC_STATE {
  LIST_ENTRY ApcListHead[2];
  PKPROCESS Process;
  UCHAR KernelApcInProgress;
  UCHAR KernelApcPending;
  UCHAR UserApcPending;
} KAPC_STATE, *PKAPC_STATE;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
  BYTE Reserved1[16];
  PVOID Reserved2[10];
  UNICODE_STRING ImagePathName;
  UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;

typedef struct _PEB_LDR_DATA {
  ULONG Length;
  BOOLEAN Initialized;
  PVOID SsHandle;
  LIST_ENTRY InLoadOrderModuleList;
  LIST_ENTRY InMemoryOrderModuleList;
  LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _PEB {
  BYTE Reserved1[2];
  BYTE BeingDebugged;
  BYTE Reserved2[1];
  PVOID Reserved3[2];
  PPEB_LDR_DATA Ldr;
  PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
  BYTE Reserved4[104];
  PVOID Reserved5[52];
  PVOID PostProcessInitRoutine;
  BYTE Reserved6[128];
  PVOID Reserved7[1];
  ULONG SessionId;
} PEB, *PPEB;

typedef enum _SYSTEM_INFORMATION_CLASS {
  SystemInformationClassMin = 0,
  SystemBasicInformation = 0,
  SystemProcessorInformation = 1,
  SystemPerformanceInformation = 2,
  SystemTimeOfDayInformation = 3,
  SystemPathInformation = 4,
  SystemNotImplemented1 = 4,
  SystemProcessInformation = 5,
  SystemProcessesAndThreadsInformation = 5,
  SystemCallCountInfoInformation = 6,
  SystemCallCounts = 6,
  SystemDeviceInformation = 7,
  SystemConfigurationInformation = 7,
  SystemProcessorPerformanceInformation = 8,
  SystemProcessorTimes = 8,
  SystemFlagsInformation = 9,
  SystemGlobalFlag = 9,
  SystemCallTimeInformation = 10,
  SystemNotImplemented2 = 10,
  SystemModuleInformation = 11,
  SystemLocksInformation = 12,
  SystemLockInformation = 12,
  SystemStackTraceInformation = 13,
  SystemNotImplemented3 = 13,
  SystemPagedPoolInformation = 14,
  SystemNotImplemented4 = 14,
  SystemNonPagedPoolInformation = 15,
  SystemNotImplemented5 = 15,
  SystemHandleInformation = 16,
  SystemObjectInformation = 17,
  SystemPageFileInformation = 18,
  SystemPagefileInformation = 18,
  SystemVdmInstemulInformation = 19,
  SystemInstructionEmulationCounts = 19,
  SystemVdmBopInformation = 20,
  SystemInvalidInfoClass1 = 20,
  SystemFileCacheInformation = 21,
  SystemCacheInformation = 21,
  SystemPoolTagInformation = 22,
  SystemInterruptInformation = 23,
  SystemProcessorStatistics = 23,
  SystemDpcBehaviourInformation = 24,
  SystemDpcInformation = 24,
  SystemFullMemoryInformation = 25,
  SystemNotImplemented6 = 25,
  SystemLoadImage = 26,
  SystemUnloadImage = 27,
  SystemTimeAdjustmentInformation = 28,
  SystemTimeAdjustment = 28,
  SystemSummaryMemoryInformation = 29,
  SystemNotImplemented7 = 29,
  SystemNextEventIdInformation = 30,
  SystemNotImplemented8 = 30,
  SystemEventIdsInformation = 31,
  SystemNotImplemented9 = 31,
  SystemCrashDumpInformation = 32,
  SystemExceptionInformation = 33,
  SystemCrashDumpStateInformation = 34,
  SystemKernelDebuggerInformation = 35,
  SystemContextSwitchInformation = 36,
  SystemRegistryQuotaInformation = 37,
  SystemLoadAndCallImage = 38,
  SystemPrioritySeparation = 39,
  SystemPlugPlayBusInformation = 40,
  SystemNotImplemented10 = 40,
  SystemDockInformation = 41,
  SystemNotImplemented11 = 41,
  /* SystemPowerInformation = 42, Conflicts with POWER_INFORMATION_LEVEL 1 */
  SystemInvalidInfoClass2 = 42,
  SystemProcessorSpeedInformation = 43,
  SystemInvalidInfoClass3 = 43,
  SystemCurrentTimeZoneInformation = 44,
  SystemTimeZoneInformation = 44,
  SystemLookasideInformation = 45,
  SystemSetTimeSlipEvent = 46,
  SystemCreateSession = 47,
  SystemDeleteSession = 48,
  SystemInvalidInfoClass4 = 49,
  SystemRangeStartInformation = 50,
  SystemVerifierInformation = 51,
  SystemAddVerifier = 52,
  SystemSessionProcessesInformation	= 53,
  SystemInformationClassMax
} SYSTEM_INFORMATION_CLASS;

 typedef struct _VM_COUNTERS {
  DWORD PeakVirtualSize;
  DWORD VirtualSize;
  DWORD PageFaultCount;
  DWORD PeakWorkingSetSize;
  DWORD WorkingSetSize;
  DWORD QuotaPeakPagedPoolUsage;
  DWORD QuotaPagedPoolUsage;
  DWORD QuotaPeakNonPagedPoolUsage;
  DWORD QuotaNonPagedPoolUsage;
  DWORD PagefileUsage;
  DWORD PeakPagefileUsage;
 } VM_COUNTERS;

typedef struct _IO_COUNTERS {
  ULONGLONG ReadOperationCount;
  ULONGLONG WriteOperationCount;
  ULONGLONG OtherOperationCount;
  ULONGLONG ReadTransferCount;
  ULONGLONG WriteTransferCount;
  ULONGLONG OtherTransferCount;
} IO_COUNTERS,
 *PIO_COUNTERS;

typedef struct _SYSTEM_THREAD_INFORMATION {
  LARGE_INTEGER   KernelTime;
  LARGE_INTEGER   UserTime;
  LARGE_INTEGER   CreateTime;
  ULONG			WaitTime;
  PVOID			StartAddress;
  CLIENT_ID	    ClientId;
  LONG     	    Priority;
  LONG      	    BasePriority;
  ULONG			ContextSwitchCount;
  LONG			State;
  LONG			WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;

typedef struct _IMAGE_DATA_DIRECTORY {
  ULONG   VirtualAddress;
  ULONG   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

typedef struct _SYSTEM_PROCESS_INFORMATION {
  ULONG			NextEntryDelta;
  ULONG			ThreadCount;
  ULONG			Reserved1[6];
  LARGE_INTEGER   CreateTime;
  LARGE_INTEGER   UserTime;
  LARGE_INTEGER   KernelTime;
  UNICODE_STRING  ProcessName;
  LONG       	    BasePriority;
  ULONG			ProcessId;
  ULONG			InheritedFromProcessId;
  ULONG			HandleCount;
  ULONG			Reserved2[2];
  VM_COUNTERS	    VmCounters;
  IO_COUNTERS	    IoCounters;
  SYSTEM_THREAD_INFORMATION  Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;

typedef struct _IMAGE_EXPORT_DIRECTORY {
  ULONG   Characteristics;
  ULONG   TimeDateStamp;
  short    MajorVersion;
  short    MinorVersion;
  ULONG   Name;
  ULONG   Base;
  ULONG   NumberOfFunctions;
  ULONG   NumberOfNames;
  ULONG   AddressOfFunctions;     // RVA from base of image
  ULONG   AddressOfNames;         // RVA from base of image
  ULONG   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

typedef struct _IMAGE_DOS_HEADER {
  short e_magic;
  short e_cblp;
  short e_cp;
  short e_crlc;
  short e_cparhdr;
  short e_minalloc;
  short e_maxalloc;
  short e_ss;
  short e_sp;
  short e_csum;
  short e_ip;
  short e_cs;
  short e_lfarlc;
  short e_ovno;
  short e_res[4];
  short e_oemid;
  short e_oeminfo;
  short e_res2[10];
  LONG e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

typedef struct _IMAGE_FILE_HEADER {
  short Machine;
  short NumberOfSections;
  ULONG TimeDateStamp;
  ULONG PointerToSymbolTable;
  ULONG NumberOfSymbols;
  short SizeOfOptionalHeader;
  short Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_OPTIONAL_HEADER {
  short Magic;
  UCHAR MajorLinkerVersion;
  UCHAR MinorLinkerVersion;
  ULONG SizeOfCode;
  ULONG SizeOfInitializedData;
  ULONG SizeOfUninitializedData;
  ULONG AddressOfEntryPoint;
  ULONG BaseOfCode;
  ULONG BaseOfData;
  ULONG ImageBase;
  ULONG SectionAlignment;
  ULONG FileAlignment;
  short MajorOperatingSystemVersion;
  short MinorOperatingSystemVersion;
  short MajorImageVersion;
  short MinorImageVersion;
  short MajorSubsystemVersion;
  short MinorSubsystemVersion;
  ULONG Win32VersionValue;
  ULONG SizeOfImage;
  ULONG SizeOfHeaders;
  ULONG CheckSum;
  short Subsystem;
  short DllCharacteristics;
  ULONG SizeOfStackReserve;
  ULONG SizeOfStackCommit;
  ULONG SizeOfHeapReserve;
  ULONG SizeOfHeapCommit;
  ULONG LoaderFlags;
  ULONG NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

typedef struct _IMAGE_NT_HEADERS {
  ULONG Signature;
  IMAGE_FILE_HEADER FileHeader;
  IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

/*                                                   */

/*  Autres */

__declspec(dllimport) SSDT KeServiceDescriptorTable;
#define HOOK_SSDT(funct2Hook,functHooked,storeOriFunct)   \
    *storeOriFunct = (ULONG)InterlockedExchange((LONG volatile*)&KeServiceDescriptorTable.ServiceTable[*(PULONG)((PUCHAR)funct2Hook+1)] , (LONG)functHooked); \

#define UNHOOK_SSDT(funct2UnHook , functOriginal) \
    InterlockedExchange((LONG volatile*)&KeServiceDescriptorTable.ServiceTable[*(PULONG)((PUCHAR)funct2UnHook+1)] , (LONG)functOriginal);

/*         */

/* Déclaration des fonctions windows utilisées */

VOID
  KeStackAttachProcess (
    __in PKPROCESS  Process,
    __out PKAPC_STATE  ApcState
    );

VOID
  KeUnstackDetachProcess(
    __in PKAPC_STATE  ApcState
    );

NTSTATUS
    WINAPI
        ZwQuerySystemInformation(
  __in       SYSTEM_INFORMATION_CLASS SystemInformationClass,
  __inout    PVOID SystemInformation,
  __in       ULONG SystemInformationLength,
  __out_opt  PULONG ReturnLength
);

NTSTATUS
  PsLookupProcessByProcessId(
    __in  HANDLE ProcessId,
    __out PEPROCESS *Process
    );

/*                                             */

/* Déclaration des fonctions que propose l'header */

int       name2Pid(char* name);
PEPROCESS name2Eprocess(char* name);
PVOID     parseEatNtdll(char* function);
PVOID     findDllImageBase(char* process , char* dll);
BOOL      hookSSDT(PULONG funct2Hook , PULONG functHooked , PULONG storeOriginalFunct);
BOOL      unHookSSDT(PULONG funct2UnHook , PULONG functOriginal);

/*                                                */


/* Définitions des fonctions */

BOOL      unHookSSDT(PULONG funct2UnHook , PULONG functOriginal)
{
        __asm
      {
        push eax
        mov  eax, CR0
        and  eax, 0FFFEFFFFh //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ET 11111111111111101111111111111111 = xxxxxxxxxxxxxxx0xxxxxxxxxxxxxxxx
        mov  CR0, eax
        pop  eax
      }
    UNHOOK_SSDT(funct2UnHook , functOriginal);
    __asm
    {
      push eax
      mov eax, CR0
      or eax, NOT 00010000h //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx OR 00000000000000010000000000000000 = xxxxxxxxxxxxxxx1xxxxxxxxxxxxxxxx
      mov CR0, eax
      pop eax
    }
    return TRUE;
}

BOOL      hookSSDT(PULONG funct2Hook , PULONG functHooked , PULONG storeOriginalFunct)
{
    __asm
      {
        push eax
        mov  eax, CR0
        and  eax, 0FFFEFFFFh //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ET 11111111111111101111111111111111 = xxxxxxxxxxxxxxx0xxxxxxxxxxxxxxxx
        mov  CR0, eax
        pop  eax
      }
    HOOK_SSDT(funct2Hook , functHooked , storeOriginalFunct);
    __asm
    {
      push eax
      mov eax, CR0
      or eax, NOT 00010000h //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx OR 00000000000000010000000000000000 = xxxxxxxxxxxxxxx1xxxxxxxxxxxxxxxx
      mov CR0, eax
      pop eax
    }

    return TRUE;
}

PVOID     findDllImageBase(char* process , char* dll)
{
    PEPROCESS pEprocess;
    PPEB pPeb;
    PPEB_LDR_DATA pPebLdr;
    PLDR_DATA_TABLE_ENTRY pCurrentLdrDataEntry , pStartLdrDataEntry;
    LIST_ENTRY listEntry;
    PLIST_ENTRY pListEntry;
    BOOLEAN isFound = FALSE;
    KAPC_STATE kApcState;
    ANSI_STRING nameProcessA;
    UNICODE_STRING nameProcessW;
    PVOID imgBase;

    RtlInitAnsiString(&nameProcessA , dll);
    RtlAnsiStringToUnicodeString(&nameProcessW , &nameProcessA , TRUE);

    pEprocess = name2Eprocess(process);
    if(pEprocess == NULL)
        return NULL;

    KeStackAttachProcess((PKPROCESS)pEprocess , &kApcState);

    pPeb                 = (PPEB)*(PULONG)((PUCHAR)pEprocess + 0x1b0); //   +0x1b0 Peb              : Ptr32 _PEB
    pPebLdr              = pPeb->Ldr;
    listEntry            = pPebLdr->InLoadOrderModuleList;

    pListEntry           = listEntry.Flink;
    pCurrentLdrDataEntry = (pStartLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry);

    while(pStartLdrDataEntry != (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink)
    {
        if(wcscmp(pCurrentLdrDataEntry->BaseDllName.Buffer , nameProcessW.Buffer) == 0)
        {
            isFound = TRUE;
            break;
        }

        pCurrentLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink;
        pListEntry = pListEntry->Flink;
    }

    RtlFreeUnicodeString(&nameProcessW);
    imgBase = pCurrentLdrDataEntry->DllBase;
    KeUnstackDetachProcess(&kApcState);

    if(!isFound)
        return NULL;


    return imgBase;
}

PVOID     parseEatNtdll(char* function)
{
    PEPROCESS pCurrentEprocess;
    KAPC_STATE kApcState;
    PPEB pPeb;
    PPEB_LDR_DATA pPebLdr;
    PLDR_DATA_TABLE_ENTRY pCurrentLdrDataEntry , pStartLdrDataEntry;
    LIST_ENTRY listEntry;
    PLIST_ENTRY pListEntry;
    BOOLEAN isFound = FALSE;
    PIMAGE_DOS_HEADER pImgDosHeader;
    PIMAGE_NT_HEADERS pImgNtHeaders;
    PIMAGE_EXPORT_DIRECTORY pImgExportDirectory;
    int nbFunctions , i;
    PULONG rvaFunctionTable , rvaNameFunctionTable , pFunction;

    pCurrentEprocess = name2Eprocess("csrss.exe");
    if(pCurrentEprocess == NULL)
        return NULL;

    KeStackAttachProcess((PKPROCESS)pCurrentEprocess , &kApcState);

    pPeb                 = (PPEB)*(PULONG)((PUCHAR)pCurrentEprocess + 0x1b0); //   +0x1b0 Peb              : Ptr32 _PEB
    pPebLdr              = pPeb->Ldr;
    listEntry            = pPebLdr->InLoadOrderModuleList;

    pListEntry           = listEntry.Flink;
    pCurrentLdrDataEntry = (pStartLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry);

    while(pStartLdrDataEntry != (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink)
    {
        if(wcscmp(pCurrentLdrDataEntry->BaseDllName.Buffer , L"ntdll.dll") == 0)
        {
            isFound = TRUE;
            break;
        }

        pCurrentLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry->Flink;
        pListEntry = pListEntry->Flink;
    }

    if(!isFound)
    {
        KeUnstackDetachProcess(&kApcState);
        return NULL;
    }

    isFound              = FALSE;
    pImgDosHeader        = (PIMAGE_DOS_HEADER)pCurrentLdrDataEntry->DllBase;
    pImgNtHeaders        = (PIMAGE_NT_HEADERS)((PUCHAR)pImgDosHeader + pImgDosHeader->e_lfanew);
    pImgExportDirectory  = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pImgDosHeader + pImgNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    nbFunctions          = pImgExportDirectory->NumberOfFunctions;
    rvaFunctionTable     = (PULONG)((PUCHAR)pImgDosHeader + pImgExportDirectory->AddressOfFunctions);
    rvaNameFunctionTable = (PULONG)((PUCHAR)pImgDosHeader + pImgExportDirectory->AddressOfNames);

    for(i = 0 ; i < nbFunctions ; i++)
    {
        if(strcmp(((PUCHAR)pImgDosHeader + rvaNameFunctionTable[i]) , function) == 0)
        {
            isFound = TRUE;
            break;
        }
    }

    if(!isFound)
    {
        KeUnstackDetachProcess(&kApcState);
        return NULL;
    }

    pFunction = (PULONG)((PUCHAR)pImgDosHeader + rvaFunctionTable[i]);

    KeUnstackDetachProcess(&kApcState);
    return pFunction;
}

int name2Pid(char* name)
{
    NTSTATUS state;
    PSYSTEM_PROCESS_INFORMATION pProcessInfo;
    ULONG size;
    UNICODE_STRING uProcName;
    ANSI_STRING    aProcName;

    RtlInitAnsiString(&aProcName , name);
    RtlAnsiStringToUnicodeString(&uProcName , &aProcName , TRUE);

    state = ZwQuerySystemInformation(SystemProcessInformation , NULL , 0 , &size);
    pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool , size , 't4pz');
    if(pProcessInfo == NULL)
        return 0;

    state = ZwQuerySystemInformation(SystemProcessInformation , pProcessInfo , size , &size);
    if(!NT_SUCCESS(state))
        return 0;

    while(pProcessInfo->NextEntryDelta != 0)
    {
        if(pProcessInfo->ProcessName.Buffer != NULL)
        {
            if(wcscmp(uProcName.Buffer , pProcessInfo->ProcessName.Buffer) == 0)
            {
                RtlFreeUnicodeString(&uProcName);
                return pProcessInfo->ProcessId;
            }
        }
        pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)pProcessInfo + pProcessInfo->NextEntryDelta);
    }

    if(wcscmp(uProcName.Buffer , pProcessInfo->ProcessName.Buffer) == 0)
    {
        RtlFreeUnicodeString(&uProcName);
        return pProcessInfo->ProcessId;
    }
    return 0;
}

PEPROCESS name2Eprocess(char* name)
{
     PEPROCESS pEprocess = NULL;
     NTSTATUS state;
     int pid;

    pid = name2Pid(name);
    if(pid == 0)
        return NULL;

    state = PsLookupProcessByProcessId((HANDLE)pid , &pEprocess);
    if(!NT_SUCCESS(state))
        return NULL;
    return pEprocess;
}

/*                           */
#endif