org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.java Source code

Java tutorial

Introduction

Here is the source code for org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.java

Source

/* This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * <p/>
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.  
 */
package org.rzo.yajsw.os.ms.win.w32;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jnacontrib.jna.Advapi32;
import jnacontrib.jna.Options;

import org.apache.commons.collections.MultiHashMap;
import org.rzo.yajsw.io.CyclicBufferFileInputStream;
import org.rzo.yajsw.io.CyclicBufferFilePrintStream;
import org.rzo.yajsw.os.AbstractProcess;
import org.rzo.yajsw.os.Process;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyAdvapi.TOKEN_PRIVILEGES;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32.MEMORY_BASIC_INFORMATION;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32.PROCESSENTRY32;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32.PROCESS_INFORMATION;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32.SECURITY_ATTRIBUTES;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32.STARTUPINFO;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.Ntdll.PEB;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.Ntdll.PEB64;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.Ntdll.PROCESS_BASIC_INFORMATION;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.Ntdll.RTL_USER_PROCESS_PARAMETERS;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.User32;
import com.sun.jna.examples.win32.W32API.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;

// TODO: Auto-generated Javadoc
/**
 * The Class WindowsXPProcess.
 */
public class WindowsXPProcess extends AbstractProcess {

    /**
     * The Interface MyUser32.
     */
    public interface MyUser32 extends User32 {
        // Method declarations, constant and structure definitions go here

        /** The INSTANCE. */
        MyUser32 INSTANCE = (MyUser32) Native.loadLibrary("User32", MyUser32.class);

        /*
         * HWND GetForegroundWindow(VOID);
         */
        /**
         * Gets the foreground window.
         * 
         * @return the pointer
         */
        Pointer GetForegroundWindow();

        /*
         * DWORD GetWindowThreadProcessId( HWND hWnd, LPDWORD lpdwProcessId );
         */
        /**
         * Gets the window thread process id.
         * 
         * @param hWnd
         *            the h wnd
         * @param lpdwProcessId
         *            the lpdw process id
         * 
         * @return the int
         */
        int GetWindowThreadProcessId(Pointer hWnd, IntByReference lpdwProcessId);

        /** The W m_ close. */
        int WM_CLOSE = 16;
        int WM_QUIT = 18;
        int WM_DESTROY = 2;

        /*
         * BOOL PostThreadMessage( DWORD idThread, UINT Msg, WPARAM wParam,
         * LPARAM lParam );
         */
        /**
         * Post thread message a.
         * 
         * @param idThread
         *            the id thread
         * @param Msg
         *            the msg
         * @param wParam
         *            the w param
         * @param lParam
         *            the l param
         * 
         * @return true, if successful
         */
        boolean PostThreadMessageA(int idThread, int Msg, int wParam, int lParam);

        /*
         * DWORD WINAPI WaitForInputIdle( __in HANDLE hProcess, __in DWORD
         * dwMilliseconds );
         */
        /**
         * Wait for input idle.
         * 
         * @param hProcess
         *            the h process
         * @param dwMilliseconds
         *            the dw milliseconds
         * 
         * @return the int
         */
        int WaitForInputIdle(Pointer hProcess, int dwMilliseconds);

        void PostMessageA(Pointer hWnd, int msg, Pointer wParam, Pointer lParam);

        public interface WNDENUMPROC extends StdCallCallback {
            /** Return whether to continue enumeration. */
            boolean callback(Pointer hWnd, int data);
        }

        boolean EnumWindows(WNDENUMPROC lpEnumFunc, int data);

    }

    /**
     * The Interface MyKernel32.
     */
    public interface MyKernel32 extends Kernel32 {

        // Method declarations, constant and structure definitions go here

        /** The INSTANCE. */
        MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("kernel32", MyKernel32.class);

        /*
         * BOOL WINAPI ReadFile( __in HANDLE hFile, __out LPVOID lpBuffer, __in
         * DWORD nNumberOfBytesToRead, __out_opt LPDWORD lpNumberOfBytesRead,
         * __inout_opt LPOVERLAPPED lpOverlapped );
         */

        boolean ReadFile(Pointer hFile, Memory lpBuffer, int nNumberOfBytesToRead,
                IntByReference lpNumberOfBytesRead, Structure lpOverlapped);

        /*
         * DWORD WINAPI GetCurrentProcessId(void);
         */
        /*
         * (non-Javadoc)
         * 
         * @see com.sun.jna.examples.win32.Kernel32#GetCurrentProcessId()
         */
        int GetCurrentProcessId();

        /*
         * DWORD WINAPI GetProcessIdOfThread( __in HANDLE Thread );
         */
        /**
         * Gets the process id of thread.
         * 
         * @param Thread
         *            the thread
         * 
         * @return the int
         */
        int GetProcessIdOfThread(Pointer Thread);

        /*
         * BOOL WINAPI CreateProcess( LPCTSTR lpApplicationName, LPTSTR
         * lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
         * LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD
         * dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory,
         * LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION
         * lpProcessInformation );
         */
        /**
         * Creates the process a.
         * 
         * @param lpApplicationName
         *            the lp application name
         * @param lpCommandLine
         *            the lp command line
         * @param lpProcessAttributes
         *            the lp process attributes
         * @param lpThreadAttributes
         *            the lp thread attributes
         * @param bInheritHandles
         *            the b inherit handles
         * @param dwCreationFlags
         *            the dw creation flags
         * @param lpEnvironment
         *            the lp environment
         * @param lpCurrentDirectory
         *            the lp current directory
         * @param lpStartupInfo
         *            the lp startup info
         * @param lpProcessInformation
         *            the lp process information
         * 
         * @return true, if successful
         */
        boolean CreateProcessA(String lpApplicationName, String lpCommandLine, Structure lpProcessAttributes,
                Structure lpThreadAttributes, boolean bInheritHandles, int dwCreationFlags, Structure lpEnvironment,
                String lpCurrentDirectory, Structure lpStartupInfo, Structure lpProcessInformation);

        boolean CreateProcessW(WString lpApplicationName, WString lpCommandLine, Structure lpProcessAttributes,
                Structure lpThreadAttributes, boolean bInheritHandles, int dwCreationFlags, Structure lpEnvironment,
                WString lpCurrentDirectory, Structure lpStartupInfo, Structure lpProcessInformation);

        /** The CREAT e_ n o_ window. */
        int CREATE_NO_WINDOW = 0x08000000;

        /** The CREAT e_ unicod e_ environment. */
        int CREATE_UNICODE_ENVIRONMENT = 0x00000400;

        /** The CREAT e_ ne w_ console. */
        int CREATE_NEW_CONSOLE = 0x00000010;

        int DETACHED_PROCESS = 0x00000008;

        /*
         * typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE
         * hThread; DWORD dwProcessId; DWORD dwThreadId; }
         */

        /**
         * The Class PROCESS_INFORMATION.
         */
        public static class PROCESS_INFORMATION extends Structure {

            /** The h process. */
            public Pointer hProcess = null;

            /** The h thread. */
            public Pointer hThread = null;

            /** The dw process id. */
            public int dwProcessId = -1;

            /** The dw thread id. */
            public int dwThreadId = -1;

        }

        /*
         * typedef struct _STARTUPINFO { DWORD cb; LPTSTR lpReserved; LPTSTR
         * lpDesktop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD
         * dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD
         * dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2;
         * LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE
         * hStdError; }
         */

        /**
         * The Class STARTUPINFO.
         */
        public static class STARTUPINFO extends Structure {

            /** The cb. */
            public int cb;

            /** The lp reserved. */
            public WString lpReserved;

            /** The lp desktop. */
            public WString lpDesktop;

            /** The lp title. */
            public WString lpTitle;

            /** The dw x. */
            public int dwX;

            /** The dw y. */
            public int dwY;

            /** The dw x size. */
            public int dwXSize;

            /** The dw y size. */
            public int dwYSize;

            /** The dw x count chars. */
            public int dwXCountChars;

            /** The dw y count chars. */
            public int dwYCountChars;

            /** The dw fill attribute. */
            public int dwFillAttribute;

            /** The dw flags. */
            public int dwFlags;

            /** The w show window. */
            public short wShowWindow;

            /** The cb reserved2. */
            public short cbReserved2;

            /** The lp reserved2. */
            public Pointer lpReserved2;

            /** The h std input. */
            public Pointer hStdInput;

            /** The h std output. */
            public Pointer hStdOutput;

            /** The h std error. */
            public Pointer hStdError;
        }

        /** The START f_ usestdhandles. */
        int STARTF_USESTDHANDLES = 256;

        /** The IDL e_ priorit y_ class. */
        int IDLE_PRIORITY_CLASS = 0x00000040;

        /** The BELO w_ norma l_ priorit y_ class. */
        int BELOW_NORMAL_PRIORITY_CLASS = 0x00004000;

        /** The NORMA l_ priorit y_ class. */
        int NORMAL_PRIORITY_CLASS = 0x00000020;

        /** The ABOV e_ norma l_ priorit y_ class. */
        int ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000;

        /** The HIG h_ priorit y_ class. */
        int HIGH_PRIORITY_CLASS = 0x00000080;

        /** The REALTIM e_ priorit y_ class. */
        int REALTIME_PRIORITY_CLASS = 0x00000100;

        /*
         * DWORD WINAPI WaitForSingleObject( HANDLE hHandle, DWORD
         * dwMilliseconds );
         */
        /**
         * Wait for single object.
         * 
         * @param handle
         *            the handle
         * @param dwMilliseconds
         *            the dw milliseconds
         * 
         * @return the int
         */
        int WaitForSingleObject(Pointer handle, int dwMilliseconds);

        /** The INFINITE. */
        int INFINITE = 0xFFFFFFFF;

        /*
         * BOOL WINAPI GetExitCodeProcess( HANDLE hProcess, LPDWORD lpExitCode
         * );
         */
        /**
         * Gets the exit code process.
         * 
         * @param hProcess
         *            the h process
         * @param lpExitCode
         *            the lp exit code
         * 
         * @return true, if successful
         */
        boolean GetExitCodeProcess(Pointer hProcess, IntByReference lpExitCode);

        /** The STIL l_ active. */
        int STILL_ACTIVE = 0x103;

        /*
         * BOOL WINAPI TerminateProcess( HANDLE hProcess, UINT uExitCode );
         */

        /**
         * Terminate process.
         * 
         * @param hProcess
         *            the h process
         * @param uExitCode
         *            the u exit code
         * 
         * @return true, if successful
         */
        boolean TerminateProcess(Pointer hProcess, int uExitCode);

        /*
         * BOOL WINAPI GetProcessAffinityMask( __in HANDLE hProcess, __out
         * PDWORD_PTR lpProcessAffinityMask, __out PDWORD_PTR
         * lpSystemAffinityMask );
         */
        /**
         * Gets the process affinity mask.
         * 
         * @param hProcess
         *            the h process
         * @param lpProcessAffinityMask
         *            the lp process affinity mask
         * @param lpSystemAffinityMask
         *            the lp system affinity mask
         * 
         * @return true, if successful
         */
        boolean GetProcessAffinityMask(Pointer hProcess, IntByReference lpProcessAffinityMask,
                IntByReference lpSystemAffinityMask);

        /*
         * BOOL WINAPI SetProcessAffinityMask( __in HANDLE hProcess, __in
         * DWORD_PTR dwProcessAffinityMask );
         */
        /**
         * Sets the process affinity mask.
         * 
         * @param hProcess
         *            the h process
         * @param dwProcessAffinityMask
         *            the dw process affinity mask
         * 
         * @return true, if successful
         */
        boolean SetProcessAffinityMask(Pointer hProcess, int dwProcessAffinityMask);

        /*
         * BOOL WINAPI CloseHandle( HANDLE hObject );
         */
        /**
         * Close handle.
         * 
         * @param hObject
         *            the h object
         * 
         * @return true, if successful
         */
        public boolean CloseHandle(Pointer hObject);

        /*
         * HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, DWORD
         * th32ProcessID );
         */
        /**
         * Creates the toolhelp32 snapshot.
         * 
         * @param dwFlags
         *            the dw flags
         * @param th32ProcessID
         *            the th32 process id
         * 
         * @return the pointer
         */
        Pointer CreateToolhelp32Snapshot(int dwFlags, int th32ProcessID);

        /** The T h32 c s_ snapprocess. */
        int TH32CS_SNAPPROCESS = 0x2;

        /*
         * BOOL WINAPI Process32First( HANDLE hSnapshot, LPPROCESSENTRY32 lppe
         * );
         */
        /**
         * Process32 first.
         * 
         * @param hSnapshot
         *            the h snapshot
         * @param lppe
         *            the lppe
         * 
         * @return true, if successful
         */
        boolean Process32First(Pointer hSnapshot, Structure lppe);

        /*
         * typedef struct tagPROCESSENTRY32 { DWORD dwSize; DWORD cntUsage;
         * DWORD th32ProcessID; ULONG_PTR th32DefaultHeapID; DWORD th32ModuleID;
         * DWORD cntThreads; DWORD th32ParentProcessID; LONG pcPriClassBase;
         * DWORD dwFlags; TCHAR szExeFile[MAX_PATH]; } PROCESSENTRY32,
         * PPROCESSENTRY32;
         */

        /**
         * The Class PROCESSENTRY32.
         */
        public static class PROCESSENTRY32 extends Structure {

            /** The dw size. */
            public int dwSize;

            /** The cnt usage. */
            public int cntUsage;

            /** The th32 process id. */
            public int th32ProcessID;

            /** The th32 default heap id. */
            public int th32DefaultHeapID;

            /** The th32 module id. */
            public int th32ModuleID;

            /** The cnt threads. */
            public int cntThreads;

            /** The th32 parent process id. */
            public int th32ParentProcessID;

            /** The pc pri class base. */
            public int pcPriClassBase;

            /** The dw flags. */
            public int dwFlags;

            /** The sz exe file. */
            public char[] szExeFile;
        }

        /** The MA x_ path. */
        int MAX_PATH = 260;

        /*
         * BOOL WINAPI Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
         */
        /**
         * Process32 next.
         * 
         * @param hSnapshot
         *            the h snapshot
         * @param lppe
         *            the lppe
         * 
         * @return true, if successful
         */
        boolean Process32Next(Pointer hSnapshot, Structure lppe);

        /*
         * HANDLE WINAPI OpenProcess( DWORD dwDesiredAccess, BOOL
         * bInheritHandle, DWORD dwProcessId );
         */
        /**
         * Open process.
         * 
         * @param dwDesiredAccess
         *            the dw desired access
         * @param bInheritHandle
         *            the b inherit handle
         * @param dwProcessId
         *            the dw process id
         * 
         * @return the pointer
         */
        Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);

        /** The PROCES s_ terminate. */
        int PROCESS_TERMINATE = 1;

        /** The PROCES s_ quer y_ information. */
        int PROCESS_QUERY_INFORMATION = 1024;

        /** The STANDAR d_ right s_ required. */
        int STANDARD_RIGHTS_REQUIRED = 0xF0000;

        /** The SYNCHRONIZE. */
        int SYNCHRONIZE = 0x100000;

        /** The PROCES s_ al l_ access. */
        int PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;

        /*
         * BOOL WINAPI GetProcessTimes( __in HANDLE hProcess, __out LPFILETIME
         * lpCreationTime, __out LPFILETIME lpExitTime, __out LPFILETIME
         * lpKernelTime, __out LPFILETIME lpUserTime );
         */
        /**
         * Gets the process times.
         * 
         * @param hProcess
         *            the h process
         * @param lpCreationTime
         *            the lp creation time
         * @param lpExitTime
         *            the lp exit time
         * @param lpKernelTime
         *            the lp kernel time
         * @param lpUserTime
         *            the lp user time
         * 
         * @return true, if successful
         */
        boolean GetProcessTimes(Pointer hProcess, LongByReference lpCreationTime, LongByReference lpExitTime,
                LongByReference lpKernelTime, LongByReference lpUserTime);

        /*
         * BOOL WINAPI CreatePipe( __out PHANDLE hReadPipe, __out PHANDLE
         * hWritePipe, __in LPSECURITY_ATTRIBUTES lpPipeAttributes, __in DWORD
         * nSize );
         */
        /**
         * Creates the pipe.
         * 
         * @param hReadPipe
         *            the h read pipe
         * @param hWritePipe
         *            the h write pipe
         * @param lpPipeAttributes
         *            the lp pipe attributes
         * @param nSize
         *            the n size
         * 
         * @return the int
         */
        int CreatePipe(PointerByReference hReadPipe, PointerByReference hWritePipe, Structure lpPipeAttributes,
                int nSize);

        /*
         * typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID
         * lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES,
         * PSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES;
         */

        /**
         * The Class SECURITY_ATTRIBUTES.
         */
        public static class SECURITY_ATTRIBUTES extends Structure {

            /** The n length. */
            public int nLength;

            /** The lp security descriptor. */
            public Pointer lpSecurityDescriptor;

            /** The b inherit handle. */
            public boolean bInheritHandle;
        }

        /*
         * BOOL WINAPI SetHandleInformation( __in HANDLE hObject, __in DWORD
         * dwMask, __in DWORD dwFlags );
         */
        /**
         * Sets the handle information.
         * 
         * @param hObject
         *            the h object
         * @param dwMask
         *            the dw mask
         * @param dwFlags
         *            the dw flags
         * 
         * @return true, if successful
         */
        boolean SetHandleInformation(Pointer hObject, int dwMask, int dwFlags);

        /** The HANDL e_ fla g_ inherit. */
        int HANDLE_FLAG_INHERIT = 0x00000001;
        int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;

        /*
         * HANDLE WINAPI CreateNamedPipe( __in LPCTSTR lpName, __in DWORD
         * dwOpenMode, __in DWORD dwPipeMode, __in DWORD nMaxInstances, __in
         * DWORD nOutBufferSize, __in DWORD nInBufferSize, __in DWORD
         * nDefaultTimeOut, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes
         * );
         */
        /**
         * Creates the named pipe a.
         * 
         * @param lpName
         *            the lp name
         * @param dwOpenMode
         *            the dw open mode
         * @param dwPipeMode
         *            the dw pipe mode
         * @param nMaxInstances
         *            the n max instances
         * @param nOutBufferSize
         *            the n out buffer size
         * @param nInBufferSize
         *            the n in buffer size
         * @param nDefaultTimeOut
         *            the n default time out
         * @param lpSecurityAttributes
         *            the lp security attributes
         * 
         * @return the pointer
         */
        Pointer CreateNamedPipeA(String lpName, int dwOpenMode, int dwPipeMode, int nMaxInstances,
                int nOutBufferSize, int nInBufferSize, int nDefaultTimeOut,
                SECURITY_ATTRIBUTES lpSecurityAttributes);

        /** The PIP e_ acces s_ outbound. */
        int PIPE_ACCESS_OUTBOUND = 0x00000002;

        /** The PIP e_ acces s_ inbound. */
        int PIPE_ACCESS_INBOUND = 0x00000001;

        /** The PIP e_ wait. */
        int PIPE_WAIT = 0x00000000;

        /** The PIP e_ nowait. */
        int PIPE_NOWAIT = 0x00000001;

        /** The GENERI c_ read. */
        int GENERIC_READ = 0x80000000;

        /**
         * Creates the file a.
         * 
         * @param lpFileName
         *            the lp file name
         * @param dwDesiredAccess
         *            the dw desired access
         * @param dwShareMode
         *            the dw share mode
         * @param lpSecurityAttributes
         *            the lp security attributes
         * @param dwCreationDisposition
         *            the dw creation disposition
         * @param dwFlagsAndAttributes
         *            the dw flags and attributes
         * @param hTemplateFile
         *            the h template file
         * 
         * @return the pointer
         */
        Pointer CreateFileA(String lpFileName, int dwDesiredAccess, int dwShareMode,
                SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes,
                Pointer hTemplateFile);

        /*
         * BOOL WINAPI ConnectNamedPipe( __in HANDLE hNamedPipe, __inout_opt
         * LPOVERLAPPED lpOverlapped );
         */
        /**
         * Connect named pipe.
         * 
         * @param hNamedPipe
         *            the h named pipe
         * @param lpOverlapped
         *            the lp overlapped
         * 
         * @return true, if successful
         */
        boolean ConnectNamedPipe(Pointer hNamedPipe, PointerByReference lpOverlapped);

        /** The INVALI d_ handl e_ value. */
        Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1);

        /*
         * BOOL WINAPI WaitNamedPipe( __in LPCTSTR lpNamedPipeName, __in DWORD
         * nTimeOut );
         */
        /**
         * Wait named pipe a.
         * 
         * @param lpNamedPipeName
         *            the lp named pipe name
         * @param nTimeOut
         *            the n time out
         * 
         * @return true, if successful
         */
        boolean WaitNamedPipeA(String lpNamedPipeName, int nTimeOut);

        /** The NMPWAI t_ us e_ defaul t_ wait. */
        int NMPWAIT_USE_DEFAULT_WAIT = 0;

        /** The NMPWAI t_ wai t_ forever. */
        int NMPWAIT_WAIT_FOREVER = 0xffffffff;

        /*
         * BOOL WINAPI SetCurrentDirectory(
        __in  LPCTSTR lpPathName
        );
         */
        boolean SetCurrentDirectoryA(String lpPathName);

        /*
         * typedef struct _MEMORY_BASIC_INFORMATION {
        PVOID  BaseAddress;
        PVOID  AllocationBase;
        DWORD  AllocationProtect;
        SIZE_T RegionSize;
        DWORD  State;
        DWORD  Protect;
        DWORD  Type;
        } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
         */
        public static class MEMORY_BASIC_INFORMATION extends Structure {
            public Pointer BaseAddress;
            public Pointer AllocationBase;
            public int AllocationProtect;
            public int RegionSize;
            public int State;
            public int Protect;
            public int Type;
        }

        public static int PAGE_NOACCESS = 0x01;
        public static int PAGE_EXECUTE = 0x10;

        /*
         * SIZE_T WINAPI VirtualQueryEx(
        __in      HANDLE hProcess,
        __in_opt  LPCVOID lpAddress,
        __out     PMEMORY_BASIC_INFORMATION lpBuffer,
        __in      SIZE_T dwLength
        );
         */
        int VirtualQueryEx(Pointer hProcess, Pointer lpAddress, Pointer lpBuffer, int dwLength);

    }

    /**
     * The Interface Ntdll.
     */
    public interface Ntdll extends StdCallLibrary {

        /** The INSTANCE. */
        Ntdll INSTANCE = (Ntdll) Native.loadLibrary("Ntdll", Ntdll.class);

        /*
         * NTOSAPI NTSTATUS NTAPI ZwReadVirtualMemory( /IN/ HANDLE
         * ProcessHandle, /IN/ PVOID BaseAddress, /OUT/ PVOID Buffer, /IN/ ULONG
         * BufferLength, /OUT/ PULONG ReturnLength /OPTIONAL/);
         */

        /**
         * Zw read virtual memory.
         * 
         * @param ProcessHandle
         *            the process handle
         * @param BaseAddress
         *            the base address
         * @param Buffer
         *            the buffer
         * @param BufferLength
         *            the buffer length
         * @param ReturnLength
         *            the return length
         * 
         * @return the int
         */
        int ZwReadVirtualMemory(Pointer ProcessHandle, Pointer BaseAddress, Pointer Buffer, int BufferLength,
                IntByReference ReturnLength);

        /*
         * NTSTATUS WINAPI ZwQueryInformationProcess( __in HANDLE ProcessHandle,
         * __in PROCESSINFOCLASS ProcessInformationClass, __out PVOID
         * ProcessInformation, __in ULONG ProcessInformationLength, __out_opt
         * PULONG ReturnLength );
         */
        /**
         * Zw query information process.
         * 
         * @param ProcessHandle
         *            the process handle
         * @param ProcessInformationClass
         *            the process information class
         * @param ProcessInformation
         *            the process information
         * @param ProcessInformationLength
         *            the process information length
         * @param ReturnLength
         *            the return length
         * 
         * @return the int
         */
        int ZwQueryInformationProcess(Pointer ProcessHandle, int ProcessInformationClass,
                Pointer ProcessInformation, int ProcessInformationLength, IntByReference ReturnLength);

        /*
         * typedef struct _PROCESS_BASIC_INFORMATION { PVOID Reserved1; PPEB
         * PebBaseAddress; PVOID Reserved2[2]; ULONG_PTR UniqueProcessId; PVOID
         * Reserved3; } PROCESS_BASIC_INFORMATION;
         */
        /**
         * The Class PROCESS_BASIC_INFORMATION.
         */
        class PROCESS_BASIC_INFORMATION extends Structure {

            /** The Reserved1. */
            public Pointer Reserved1;

            /** The Peb base address. */
            public Pointer PebBaseAddress;

            /** The Reserved2. */
            public int[] Reserved2 = new int[2];

            /** The Unique process id. */
            public Pointer UniqueProcessId;

            /** The Reserved3. */
            public Pointer Reserved3;
        }

        /*
         * 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]; PPS_POST_PROCESS_INIT_ROUTINE
         * PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1];
         * ULONG SessionId; } PEB, PPEB;
         */
        /**
         * The Class PEB.
         */
        class PEB extends Structure {

            /** The Reserved1. */
            public byte[] Reserved1 = new byte[2];

            /** The Being debugged. */
            public byte BeingDebugged;

            /** The Reserved2. */
            public byte Reserved2;

            /** The Reserved3. */
            public int[] Reserved3 = new int[2];

            /** The Ldr. */
            public Pointer Ldr;

            /** The Process parameters. */
            public Pointer ProcessParameters;

            /** The Reserved4. */
            public byte[] Reserved4 = new byte[104];

            /** The Reserved5. */
            public int[] Reserved5 = new int[52];

            /** The Post process init routine. */
            public Pointer PostProcessInitRoutine;

            /** The Reserved6. */
            public byte[] Reserved6 = new byte[128];

            /** The Reserved7. */
            public int[] Reserved7 = new int[1];

            /** The Session id. */
            public int SessionId;

        }

        /*
         * typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE
         * Reserved2[21]; PPEB_LDR_DATA LoaderData; PRTL_USER_PROCESS_PARAMETERS
         * ProcessParameters; BYTE Reserved3[520]; PPS_POST_PROCESS_INIT_ROUTINE
         * PostProcessInitRoutine; BYTE Reserved4[136]; ULONG SessionId; } PEB;
         */
        class PEB64 extends Structure {
            public byte[] Reserved1 = new byte[2];
            public byte BeingDebugged;
            public byte[] Reserved2 = new byte[21];;
            public Pointer Ldr;
            public Pointer ProcessParameters;
            public byte[] Reserved3 = new byte[520];
            public Pointer PostProcessInitRoutine;
            public byte[] Reserved4 = new byte[136];
            public int SessionId;
        }

        /*
         * typedef struct _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; 16
         * PVOID Reserved2[10]; 40 UNICODE_STRING ImagePathName; UNICODE_STRING
         * CommandLine; } RTL_USER_PROCESS_PARAMETERS,
         * PRTL_USER_PROCESS_PARAMETERS;
         * 
         * typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; 4
         * ULONG Length; 8 ULONG Flags; 12 ULONG DebugFlags; 16 PVOID
         * ConsoleHandle; 4 ULONG ConsoleFlags; 8 HANDLE StdInputHandle; 12
         * HANDLE StdOutputHandle; 16 HANDLE StdErrorHandle; 20 UNICODE_STRING
         * CurrentDirectoryPath; 28 HANDLE CurrentDirectoryHandle; 32
         * UNICODE_STRING DllPath; 40 UNICODE_STRING ImagePathName; 48
         * UNICODE_STRING CommandLine; 56 PVOID Environment; 4 ULONG
         * StartingPositionLeft; 8 ULONG StartingPositionTop; 12 ULONG Width; 16
         * ULONG Height; 20 ULONG CharWidth; 24 ULONG CharHeight; 28 ULONG
         * ConsoleTextAttributes; 32 ULONG WindowFlags; 36 ULONG
         * ShowWindowFlags; 40 UNICODE_STRING WindowTitle; 48 UNICODE_STRING
         * DesktopName; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData;
         * RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; }
         * RTL_USER_PROCESS_PARAMETERS,PRTL_USER_PROCESS_PARAMETERS;
         */

        /**
         * The Class RTL_USER_PROCESS_PARAMETERS.
         */
        class RTL_USER_PROCESS_PARAMETERS extends Structure {

            /** The Reserved1. */
            public byte[] Reserved1 = new byte[16];

            /** The Reserved2. */
            public int[] Reserved2 = new int[5];
            // public int[] Reserved2 = new int[16];

            public UNICODE_STRING CurrentDirectoryPath;
            public Pointer CurrentDirectoryHandle;
            public UNICODE_STRING DllPath;

            /** The Image path name. */
            public UNICODE_STRING ImagePathName;

            /** The Command line. */
            public UNICODE_STRING CommandLine;
            public Pointer Environment; // new

            public int[] reserved3 = new int[9]; //int[10];

            public UNICODE_STRING WindowTitle;

        }

        /*
         * typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT
         * MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING,
         * PLSA_UNICODE_STRING, UNICODE_STRING, PUNICODE_STRING;
         */
        /**
         * The Class UNICODE_STRING.
         */
        class UNICODE_STRING extends Structure {

            /** The Length. */
            public short Length = 0;

            /** The Maximum length. */
            public short MaximumLength;

            /** The Buffer. */
            public Pointer Buffer;
        }
    }

    public interface MyAdvapi extends Advapi32 {
        MyAdvapi INSTANCE = (MyAdvapi) Native.loadLibrary("Advapi32", MyAdvapi.class, Options.UNICODE_OPTIONS);

        /*
         * BOOL WINAPI LookupAccountSid( __in_opt LPCTSTR lpSystemName, __in
         * PSID lpSid, __out_opt LPTSTR lpName, __inout LPDWORD cchName,
         * __out_opt LPTSTR lpReferencedDomainName, __inout LPDWORD
         * cchReferencedDomainName, __out PSID_NAME_USE peUse );
         */
        boolean LookupAccountSidW(String lpSystemName, Pointer lpSid, Memory lpName, IntByReference cchName,
                Memory lpReferencedDomainName, IntByReference cchReferencedDomainName, IntByReference peUse);

        /*
         * typedef struct _SID_AND_ATTRIBUTES { PSID Sid; DWORD Attributes; }
         * SID_AND_ATTRIBUTES,PSID_AND_ATTRIBUTES;
         */
        static class SID_AND_ATTRIBUTES extends Structure {
            public Pointer Sid;
            public int Attributes;
        }

        /*
         * typedef struct _TOKEN_USER { SID_AND_ATTRIBUTES User; } TOKEN_USER,
         * PTOKEN_USER;
         */
        static class TOKEN_USER extends Structure {
            public SID_AND_ATTRIBUTES User;

            public TOKEN_USER(Pointer p) {
                super();
                this.useMemory(p);
                this.read();
            }
        }

        public static final int TokenPrivileges = 3;
        public static final int TokenUser = 1;

        /*
         * BOOL WINAPI GetTokenInformation( __in HANDLE TokenHandle, __in
         * TOKEN_INFORMATION_CLASS TokenInformationClass, __out_opt LPVOID
         * TokenInformation, __in DWORD TokenInformationLength, __out PDWORD
         * ReturnLength );
         */
        boolean GetTokenInformation(Pointer TokenHandle, int TokenInformationClass, Memory TokenInformation,
                int TokenInformationLength, IntByReference ReturnLength);

        /*
         * BOOL WINAPI InitializeSecurityDescriptor( __out PSECURITY_DESCRIPTOR
         * pSecurityDescriptor, __in DWORD dwRevision );
         */
        boolean InitializeSecurityDescriptor(Memory pSecurityDescriptor, int dwRevision);

        public static final int SECURITY_DESCRIPTOR_MIN_LENGTH = 20;
        public static final int SECURITY_DESCRIPTOR_REVISION = 1;

        /*
         * BOOL WINAPI SetSecurityDescriptorSacl( __inout PSECURITY_DESCRIPTOR
         * pSecurityDescriptor, __in BOOL bSaclPresent, __in_opt PACL pSacl,
         * __in BOOL bSaclDefaulted );
         */
        boolean SetSecurityDescriptorDacl(Pointer pSecurityDescriptor, boolean bSaclPresent, Pointer pSacl,
                boolean bSaclDefaulted);

        public static int SE_PRIVILEGE_ENABLED = 2;

        /*
         * typedef struct _LUID { DWORD LowPart; LONG HighPart; } LUID,PLUID;
         */
        static class LUID extends Structure {
            public int LowPart;
            public int HighPart;
        }

        /*
         * typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; DWORD Attributes; }
         * LUID_AND_ATTRIBUTES,PLUID_AND_ATTRIBUTES;
         */
        static class LUID_AND_ATTRIBUTES extends Structure {
            public LUID Luid;
            public int Attributes;
        }

        /*
         * typedef struct _TOKEN_PRIVILEGES { DWORD PrivilegeCount;
         * LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; } TOKEN_PRIVILEGES,
         * PTOKEN_PRIVILEGES;
         */
        static class TOKEN_PRIVILEGES extends Structure {
            public int PrivilegeCount = 1;
            public LUID_AND_ATTRIBUTES[] Privileges = new LUID_AND_ATTRIBUTES[1];

            public TOKEN_PRIVILEGES() {
                super();
                Privileges[0] = new LUID_AND_ATTRIBUTES();
            }

            public TOKEN_PRIVILEGES(Pointer p) {
                super();
                PrivilegeCount = p.getInt(0);
                Privileges = new LUID_AND_ATTRIBUTES[PrivilegeCount];
                this.useMemory(p);
                this.read();
            }

        }

        /*
         * BOOL WINAPI AdjustTokenPrivileges( __in HANDLE TokenHandle, __in BOOL
         * DisableAllPrivileges, __in_opt PTOKEN_PRIVILEGES NewState, __in DWORD
         * BufferLength, __out_opt PTOKEN_PRIVILEGES PreviousState, __out_opt
         * PDWORD ReturnLength );
         */
        boolean AdjustTokenPrivileges(Pointer TokenHandle, boolean DisableAllPrivileges, TOKEN_PRIVILEGES NewState,
                int BufferLength, PointerByReference PreviousState, IntByReference ReturnLength);

        /*
         * BOOL WINAPI LookupPrivilegeValue( __in_opt LPCTSTR lpSystemName, __in
         * LPCTSTR lpName, __out PLUID lpLuid );
         */
        boolean LookupPrivilegeValueA(String lpSystemName, String lpName, LUID lpLuid);

        public static final String SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
        public static final String SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
        public static final String SE_DEBUG_NAME = "SeDebugPrivilege";
        public static final String SE_TCB_NAME = "SeTcbPrivilege";

        /*
         * BOOL WINAPI OpenProcessToken( __in HANDLE ProcessHandle, __in DWORD
         * DesiredAccess, __out PHANDLE TokenHandle );
         */
        boolean OpenProcessToken(com.sun.jna.examples.win32.W32API.HANDLE ProcessHandle, int DesiredAccess,
                PointerByReference TokenHandle);

        public static final int STANDARD_RIGHTS_READ = 0x20000;
        public static final int STANDARD_RIGHTS_WRITE = 0x20000;
        public static final int TOKEN_QUERY = 0x0008;
        public static final int TOKEN_ADJUST_PRIVILEGES = 0x0020;
        public static final int TOKEN_ADJUST_GROUPS = 0x0040;
        public static final int TOKEN_ADJUST_DEFAULT = 0x0080;
        public static final int TOKEN_DUPLICATE = 0x0002;
        public static final int TOKEN_IMPERSONATE = 0x0004;

        public static final int TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY;

        public static final int TOKEN_WRITE = STANDARD_RIGHTS_WRITE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS
                | TOKEN_ADJUST_DEFAULT;

        /*
         * BOOL WINAPI CreateProcessWithLogonW( __in LPCWSTR lpUsername,
         * __in_opt LPCWSTR lpDomain, __in LPCWSTR lpPassword, __in DWORD
         * dwLogonFlags, __in_opt LPCWSTR lpApplicationName, __inout_opt LPWSTR
         * lpCommandLine, __in DWORD dwCreationFlags, __in_opt LPVOID
         * lpEnvironment, __in_opt LPCWSTR lpCurrentDirectory, __in
         * LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION
         * lpProcessInfo );
         */
        boolean CreateProcessWithLogonW(WString lpUsername, WString lpDomain, WString lpPassword, int dwLogonFlags,
                WString lpApplicationName, WString lpCommandLine, int dwCreationFlags, Pointer lpEnvironment,
                WString lpCurrentDirectory, Structure lpStartupInfo, Structure lpProcessInfo);

        public static final int LOGON_WITH_PROFILE = 0x00000001;
        public static final int LOGON_NETCREDENTIALS_ONLY = 0x00000002;

        /*
         * BOOL LogonUser( __in LPTSTR lpszUsername, __in_opt LPTSTR lpszDomain,
         * __in LPTSTR lpszPassword, __in DWORD dwLogonType, __in DWORD
         * dwLogonProvider, __out PHANDLE phToken );
         */
        boolean LogonUserA(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType,
                int dwLogonProvider, PointerByReference phToken);

        boolean LogonUserW(WString lpszUsername, WString lpszDomain, WString lpszPassword, int dwLogonType,
                int dwLogonProvider, PointerByReference phToken);

        public static final int LOGON32_LOGON_INTERACTIVE = 2;
        public static final int LOGON32_LOGON_NETWORK = 3;
        public static final int LOGON32_LOGON_BATCH = 4;
        public static final int LOGON32_LOGON_SERVICE = 5;
        public static final int LOGON32_LOGON_UNLOCK = 7;
        public static final int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
        public static final int LOGON32_LOGON_NEW_CREDENTIALS = 9;

        public static final int LOGON32_PROVIDER_DEFAULT = 0;
        public static final int LOGON32_PROVIDER_WINNT35 = 1;
        public static final int LOGON32_PROVIDER_WINNT40 = 2;
        public static final int LOGON32_PROVIDER_WINNT50 = 3;

        /*
         * BOOL WINAPI ImpersonateLoggedOnUser( __in HANDLE hToken );
         */
        boolean ImpersonateLoggedOnUser(Pointer hToken);

        /*
         * BOOL WINAPI CreateProcessAsUser( __in_opt HANDLE hToken, __in_opt
         * LPCTSTR lpApplicationName, __inout_opt LPTSTR lpCommandLine, __in_opt
         * LPSECURITY_ATTRIBUTES lpProcessAttributes, __in_opt
         * LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles,
         * __in DWORD dwCreationFlags, __in_opt LPVOID lpEnvironment, __in_opt
         * LPCTSTR lpCurrentDirectory, __in LPSTARTUPINFO lpStartupInfo, __out
         * LPPROCESS_INFORMATION lpProcessInformation );
         */
        boolean CreateProcessAsUserW(Pointer hToken, WString lpApplicationName, WString lpCommandLine,
                Structure lpProcessAttributes, Structure lpThreadAttributes, boolean bInheritHandles,
                int dwCreationFlags, Structure lpEnvironment, WString lpCurrentDirectory, Structure lpStartupInfo,
                Structure lpProcessInformation);

        static class SECURITY_ATTRIBUTES {
            public int nLength;
            public Pointer lpSecurityDescriptor;
            boolean bInheritHandle;
        }

    }

    public interface Secur32 extends StdCallLibrary {

        /** The INSTANCE. */
        Secur32 INSTANCE = (Secur32) Native.loadLibrary("Secur32", Secur32.class);

        /*
         * BOOLEAN WINAPI GetUserNameEx( __in EXTENDED_NAME_FORMAT NameFormat,
         * __out LPTSTR lpNameBuffer, __inout PULONG lpnSize );
         */
        boolean GetUserNameEx(int NameFormat, Memory lpNameBuffer, IntByReference lpnSize);

    }

    /** The _startup info. */
    STARTUPINFO _startupInfo;

    /** The _process information. */
    volatile PROCESS_INFORMATION _processInformation;

    /** The in read. */
    PointerByReference inRead = null;

    /** The in write. */
    PointerByReference inWrite = null;

    /** The out read. */
    PointerByReference outRead = null;

    /** The out write. */
    PointerByReference outWrite = null;

    /** The err read. */
    PointerByReference errRead = null;

    /** The err write. */
    PointerByReference errWrite = null;

    /** The sa. */
    SECURITY_ATTRIBUTES sa;

    /** The m_h out pipe. */
    Pointer m_hOutPipe = null;

    /** The m_h err pipe. */
    Pointer m_hErrPipe = null;

    /** The m_h in pipe. */
    Pointer m_hInPipe = null;

    /** The in write pipe. */
    Pointer inWritePipe = null;

    /** The out read pipe. */
    Pointer outReadPipe = null;

    /** The err read pipe. */
    Pointer errReadPipe = null;

    /**
     * Gets the process.
     * 
     * @param pid
     *            the pid
     * 
     * @return the process
     */
    public static Process getProcess(int pid) {
        WindowsXPProcess result = new WindowsXPProcess();
        Pointer hProcess = MyKernel32.INSTANCE.OpenProcess(MyKernel32.PROCESS_ALL_ACCESS, false, pid);
        if (hProcess == null)
            hProcess = MyKernel32.INSTANCE.OpenProcess(MyKernel32.PROCESS_QUERY_INFORMATION, false, pid);
        if (hProcess == null)
            return null;

        result._pid = pid;
        result._processInformation = new PROCESS_INFORMATION();
        result._processInformation.dwProcessId = pid;
        result._processInformation.hProcess = hProcess;
        result._cmd = result.getCommandLineInternal();
        // this does not always work (why ??), if so try again, then this
        // normally does
        // on win64 PEB of 64 bit cannot be accessed from wow -> use wmi
        if (result._cmd.equals("?"))
            result._cmd = result.getCommandLineInternalWMI();
        //System.out.println(result._cmd);
        PointerByReference hToken = new PointerByReference();
        HANDLE hp = new HANDLE();
        hp.setPointer(hProcess);
        if (MyAdvapi.INSTANCE.OpenProcessToken(hp, MyAdvapi.TOKEN_READ, hToken)) {
            IntByReference dwSize = new IntByReference();
            MyAdvapi.INSTANCE.GetTokenInformation(hToken.getValue(), MyAdvapi.TokenUser, null, 0, dwSize);
            {
                Memory pTokenUser = new Memory(dwSize.getValue());
                if (MyAdvapi.INSTANCE.GetTokenInformation(hToken.getValue(), MyAdvapi.TokenUser, pTokenUser,
                        dwSize.getValue(), dwSize)) {
                    MyAdvapi.TOKEN_USER tokenUser = new MyAdvapi.TOKEN_USER(pTokenUser);
                    Pointer lpSid = tokenUser.User.Sid;
                    Memory lpName = new Memory(256);
                    IntByReference cchName = new IntByReference();
                    cchName.setValue(256);
                    Memory lpReferencedDomainName = new Memory(256);
                    IntByReference cchReferencedDomainName = new IntByReference();
                    cchReferencedDomainName.setValue(256);
                    IntByReference peUse = new IntByReference();
                    if (MyAdvapi.INSTANCE.LookupAccountSidW(null, lpSid, lpName, cchName, lpReferencedDomainName,
                            cchReferencedDomainName, peUse))

                        result._user = lpReferencedDomainName.getString(0, true) + "\\" + lpName.getString(0, true);
                    ;
                    //System.out.println(result._user);
                }
            }
            if (result._user == null)
                System.out.println(MyKernel32.INSTANCE.GetLastError());
            MyKernel32.INSTANCE.CloseHandle(hToken.getValue());
        }
        return result;
    }

    private boolean setPrivilege(Pointer hToken, String lpszPrivilege, boolean bEnablePrivilege) {
        TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();
        MyAdvapi.LUID luid = new MyAdvapi.LUID();
        luid.size();

        if (!MyAdvapi.INSTANCE.LookupPrivilegeValueA(null, lpszPrivilege, luid))
            return false;

        tp.Privileges[0].Luid = luid;
        tp.write();

        if (bEnablePrivilege)
            tp.Privileges[0].Attributes = MyAdvapi.SE_PRIVILEGE_ENABLED;
        else
            tp.Privileges[0].Attributes = 0;

        int size = tp.size();
        boolean result = MyAdvapi.INSTANCE.AdjustTokenPrivileges(hToken, false, tp, 0, null, null);
        // return GetLastError() == ERROR_SUCCESS;
        if (!result) {
            log("error setting privliges " + Integer.toHexString(MyKernel32.INSTANCE.GetLastError()));
            log("error setting privliges " + MyKernel32.INSTANCE.GetLastError());
        }

        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#start()
     */
    public boolean start() {
        boolean result = false;

        if (isRunning()) {
            log("process already running -> abort start");
            return false;
        } else {
            setPid(-1);
            setExitCode(-1);
        }
        _started = false;

        int PIPE_SIZE = 1024; // buffer size for pipes
        int PIPE_TIMEOUT = 12000; // time to wait for pipe

        if (_arrCmd == null && _cmd == null)
            return false;
        if (_cmd == null) {
            _cmd = "";
            for (String cmd : _arrCmd)
                if (cmd.startsWith("\""))
                    _cmd += cmd + " ";
                else
                    _cmd += '"' + cmd + "\" ";
            //_cmd += cmd + " ";
        }
        log("exec: " + _cmd);
        if (_processInformation != null) {
            log("process not correctly disposed -> abort start");
            return false;
        }
        try {
            destroyed = false;
            _startupInfo = new STARTUPINFO();
            _startupInfo.clear();
            _processInformation = new PROCESS_INFORMATION();
            _processInformation.clear();
            if (_pipeStreams) {
                if (sa == null) {
                    sa = new SECURITY_ATTRIBUTES();
                    sa.clear();
                    sa.nLength = sa.size();
                    sa.lpSecurityDescriptor = null;
                    sa.bInheritHandle = true;// 1; // true otherwise streams are
                    // not piped
                }
                inRead = new PointerByReference();
                inWrite = new PointerByReference();
                outRead = new PointerByReference();
                outWrite = new PointerByReference();
                errRead = new PointerByReference();
                errWrite = new PointerByReference();

                if (MyKernel32.INSTANCE.CreatePipe(inRead, inWrite, sa, 0) == 0
                        || MyKernel32.INSTANCE.CreatePipe(outRead, outWrite, sa, 0) == 0
                        || MyKernel32.INSTANCE.CreatePipe(errRead, errWrite, sa, 0) == 0) {
                    log("Error in CreatePipe " + Integer.toHexString(MyKernel32.INSTANCE.GetLastError()));
                    return false;
                }

                _startupInfo.dwFlags = MyKernel32.STARTF_USESTDHANDLES;
                _startupInfo.hStdInput = inRead.getValue();
                _startupInfo.hStdOutput = outWrite.getValue();
                _startupInfo.hStdError = errWrite.getValue();

                if (!MyKernel32.INSTANCE.SetHandleInformation(inWrite.getValue(), MyKernel32.HANDLE_FLAG_INHERIT, 0)
                        || !MyKernel32.INSTANCE.SetHandleInformation(outRead.getValue(),
                                MyKernel32.HANDLE_FLAG_INHERIT, 0)
                        || !MyKernel32.INSTANCE.SetHandleInformation(errRead.getValue(),
                                MyKernel32.HANDLE_FLAG_INHERIT, 0)
                        // for some unknown reason: if we add the following lines we do not get "operation on non socket" error in mina 
                        || !MyKernel32.INSTANCE.SetHandleInformation(inWrite.getValue(),
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE,
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE)
                        || !MyKernel32.INSTANCE.SetHandleInformation(outRead.getValue(),
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE,
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE)
                        || !MyKernel32.INSTANCE.SetHandleInformation(errRead.getValue(),
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE,
                                MyKernel32.HANDLE_FLAG_PROTECT_FROM_CLOSE))

                {
                    log("error in set handle -> abort start");
                    return false;
                }
                if (this._redirectErrorStream)
                    MyKernel32.INSTANCE.SetHandleInformation(errRead.getValue(), MyKernel32.HANDLE_FLAG_INHERIT, 0);

            }

            int creationFlag = 0;
            if (!_visible) {
                creationFlag |= MyKernel32.CREATE_NO_WINDOW | MyKernel32.CREATE_UNICODE_ENVIRONMENT;
                _startupInfo.lpTitle = null;
            } else {
                creationFlag |= MyKernel32.CREATE_NEW_CONSOLE | MyKernel32.CREATE_UNICODE_ENVIRONMENT;
                _startupInfo.lpTitle = new WString(_title);
            }

            creationFlag |= getPriorityFlag();

            // do not inherit handles. otherwise resources are not freed if
            // parent is killed
            // inherit only when we need to pipe the streams
            _startupInfo.write();
            WString cmd = new WString(_cmd);
            WString wDir = getWorkingDir() == null ? null : new WString(getWorkingDir());
            String stdUser = standardizeUser(_user);
            if (stdUser == null || stdUser.equals(currentUser())) {
                result = MyKernel32.INSTANCE.CreateProcessW(null, cmd, null, null, _pipeStreams, creationFlag, null,
                        wDir, _startupInfo, _processInformation);
            } else {
                WString user = null;
                ;
                WString domain = null;
                ;
                int i = _user.lastIndexOf("\\");
                if (i > 0) {
                    user = new WString(_user.substring(_user.lastIndexOf("\\") + 1));
                    domain = new WString(_user.substring(0, _user.lastIndexOf("\\")));
                } else
                    user = new WString(_user);
                WString password = null;
                if (_password != null)
                    password = new WString(_password);

                if (!"SYSTEM".equals(currentUserName())) {
                    // createProcessWithLogon : cmd line is only 1024 char long
                    // parent process is not current process.
                    // -> use CreateProcessAsUser
                    // result = MyAdvapi.INSTANCE.CreateProcessWithLogonW(user,
                    // domain, password, MyAdvapi.LOGON_WITH_PROFILE, null, cmd,
                    // creationFlag, null, wDir, _startupInfo,
                    // _processInformation);

                    /**/
                    PointerByReference phToken = new PointerByReference();

                    String stUser = user.toString();
                    String stDomain = domain == null ? null : domain.toString();
                    String stPassword = password == null ? "" : password.toString();
                    result = true;
                    // result = MyAdvapi.INSTANCE.LogonUserA(stUser, stDomain,
                    // stPassword, MyAdvapi.LOGON32_LOGON_NEW_CREDENTIALS,
                    // MyAdvapi.LOGON32_PROVIDER_WINNT50, phToken);
                    if (result) {
                        // HANDLE hCurrentProcess =
                        // MyKernel32.INSTANCE.GetCurrentProcess();
                        // PointerByReference hTokenSelf = new
                        // PointerByReference();
                        // result =
                        // MyAdvapi.INSTANCE.OpenProcessToken(hCurrentProcess,
                        // MyAdvapi.TOKEN_READ | MyAdvapi.TOKEN_WRITE |
                        // MyAdvapi.TOKEN_DUPLICATE |
                        // MyAdvapi.TOKEN_IMPERSONATE, hTokenSelf );
                        /*
                         * Memory pSD = new
                         * Memory(MyAdvapi.SECURITY_DESCRIPTOR_MIN_LENGTH);
                         * pSD.clear(); if (result) result =
                         * MyAdvapi.INSTANCE.InitializeSecurityDescriptor(pSD,
                         * MyAdvapi.SECURITY_DESCRIPTOR_REVISION);
                         * 
                         * if (result) result =
                         * MyAdvapi.INSTANCE.SetSecurityDescriptorDacl(pSD,
                         * true, null, false);
                         */
                        if (result) {

                            /*
                             * SECURITY_ATTRIBUTES sap = new
                             * SECURITY_ATTRIBUTES(); sap.clear(); sap.nLength =
                             * sap.size(); sap.lpSecurityDescriptor = pSD;
                             * sap.bInheritHandle = false;
                             */
                            // result =
                            // MyAdvapi.INSTANCE.ImpersonateLoggedOnUser(phToken.getValue());
                            /**/// System.out.println(MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME));
                            // System.out.println(MyAdvapi.SE_INCREASE_QUOTA_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_INCREASE_QUOTA_NAME));
                            // System.out.println(MyAdvapi.SE_DEBUG_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_DEBUG_NAME));
                            // System.out.println(MyAdvapi.SE_TCB_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_TCB_NAME));
                            // */
                            /**/if (result) {
                                // result =
                                // setPrivilege(hTokenSelf.getValue(),
                                // MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME, true)
                                // && setPrivilege(hTokenSelf.getValue(),
                                // MyAdvapi.SE_INCREASE_QUOTA_NAME, true)
                                // && setPrivilege(hTokenSelf.getValue(),
                                // MyAdvapi.SE_DEBUG_NAME, true)
                                // && setPrivilege(hTokenSelf.getValue(),
                                // MyAdvapi.SE_TCB_NAME, true)
                                ;
                            }
                            // System.out.println(MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME));
                            // System.out.println(MyAdvapi.SE_INCREASE_QUOTA_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_INCREASE_QUOTA_NAME));
                            // System.out.println(MyAdvapi.SE_DEBUG_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_DEBUG_NAME));
                            // System.out.println(MyAdvapi.SE_TCB_NAME+" "+this.doesUserHavePrivilege(MyAdvapi.SE_TCB_NAME));
                            // */
                            // MyKernel32.INSTANCE.CloseHandle(hTokenSelf.getValue());
                            if (!doesUserHavePrivilege(MyAdvapi.SE_ASSIGNPRIMARYTOKEN_NAME))
                                log("Process does not have the SE_ASSIGNPRIMARYTOKEN_NAME privilege !!");

                            if (!doesUserHavePrivilege(MyAdvapi.SE_INCREASE_QUOTA_NAME))
                                log("Process does not have the SE_INCREASE_QUOTA_NAME privilege !!");

                            result = MyAdvapi.INSTANCE.LogonUserA(stUser, stDomain, stPassword,
                                    MyAdvapi.LOGON32_LOGON_INTERACTIVE, MyAdvapi.LOGON32_PROVIDER_DEFAULT, phToken);
                            if (result)
                                // result =
                                // MyAdvapi.INSTANCE.CreateProcessWithLogonW(user,
                                // domain, password,
                                // MyAdvapi.LOGON_NETCREDENTIALS_ONLY, null,
                                // cmd, creationFlag, null, wDir, _startupInfo,
                                // _processInformation);
                                result = MyAdvapi.INSTANCE.CreateProcessAsUserW(phToken.getValue(), null, cmd, null, // sap,
                                        null, true, // _pipeStreams,
                                        creationFlag, null, null, // getWorkingDir(),
                                        _startupInfo, _processInformation);
                        }

                    }
                    /**/

                } else {
                    /*
                     * _startupInfo = new STARTUPINFO(); _startupInfo.clear();
                     * _processInformation = new PROCESS_INFORMATION();
                     * _processInformation.clear();
                     */
                    PointerByReference phToken = new PointerByReference();

                    String stUser = user.toString();
                    String stDomain = domain == null ? null : domain.toString();
                    String stPassword = password == null ? "" : password.toString();

                    result = MyAdvapi.INSTANCE.LogonUserW(user, domain, password,
                            MyAdvapi.LOGON32_LOGON_INTERACTIVE, MyAdvapi.LOGON32_PROVIDER_DEFAULT, phToken);
                    log("logonUserA " + result);
                    if (result) {
                        // result =
                        // MyAdvapi.INSTANCE.ImpersonateLoggedOnUser(phToken.getValue());
                        if (result)
                            // result =
                            // MyAdvapi.INSTANCE.CreateProcessWithLogonW(user,
                            // domain, password,
                            // MyAdvapi.LOGON_NETCREDENTIALS_ONLY, null, cmd,
                            // creationFlag, null, wDir, _startupInfo,
                            // _processInformation);
                            result = MyAdvapi.INSTANCE.CreateProcessAsUserW(phToken.getValue(), null, cmd, null,
                                    null, _pipeStreams, creationFlag, null, new WString(getWorkingDir()),
                                    _startupInfo, _processInformation);

                    }

                }
            }

            if (!result) {
                int err = MyKernel32.INSTANCE.GetLastError();
                log("could not start process " + Integer.toHexString(err));
                log(getSystemError(err));
                return result;
            }
            _started = true;

            // Thread.sleep(1000);

            int res = MyUser32.INSTANCE.WaitForInputIdle(_processInformation.hProcess, 2000);
            if (res > 0) {
                log("Warning: WaitForInputIdle returned " + res);
                // return false;
            }

            int affinity = getProcessAffinity();
            if (affinity > 0) {
                if (!MyKernel32.INSTANCE.SetProcessAffinityMask(_processInformation.hProcess, affinity))
                    log("could not set process affinity");
            }

            if (_pipeStreams) {

                // Thread.sleep(15000);
                /*
                 * Memory buf = new Memory(1); IntByReference rres = new
                 * IntByReference(); System.out.println("readddd"); boolean x =
                 * MyKernel32.INSTANCE.ReadFile(outRead.getValue(), buf, (int)
                 * buf.getSize(), rres, null); if (!x)
                 * System.out.println("read error"); else
                 * System.out.println(buf.getByte(0));
                 */

                writefd(in_fd, inWrite.getValue());
                writefd(out_fd, outRead.getValue());
                writefd(err_fd, errRead.getValue());

                _outputStream = new BufferedOutputStream(new FileOutputStream(in_fd));
                _inputStream = new BufferedInputStream(new FileInputStream(out_fd));
                _errorStream = new BufferedInputStream(new FileInputStream(err_fd));

                MyKernel32.INSTANCE.CloseHandle(inRead.getValue());
                MyKernel32.INSTANCE.CloseHandle(outWrite.getValue());
                MyKernel32.INSTANCE.CloseHandle(errWrite.getValue());

            } else if (_teeName != null && _tmpPath != null) {
                File f = new File(_tmpPath);
                if (!f.exists())
                    f.mkdir();
                _outputStream = new CyclicBufferFilePrintStream(new File(_tmpPath, "in_" + _teeName));
                _inputStream = new CyclicBufferFileInputStream(new File(_tmpPath, "out_" + _teeName));
                _errorStream = new CyclicBufferFileInputStream(new File(_tmpPath, "err_" + _teeName));
            }

            _pid = _processInformation.dwProcessId;
        } catch (Exception ex) {
            log("exception in process start: " + ex);
            ex.printStackTrace();
        }

        return result;
    }

    /**
     * Gets the process affinity.
     * 
     * @return the process affinity
     */
    private int getProcessAffinity() {
        if (_cpuAffinity <= 0)
            return 0;
        IntByReference lpProcessAffinityMask = new IntByReference();
        IntByReference lpSystemAffinityMask = new IntByReference();
        if (MyKernel32.INSTANCE.GetProcessAffinityMask(_processInformation.hProcess, lpProcessAffinityMask,
                lpSystemAffinityMask))
            return lpSystemAffinityMask.getValue() & _cpuAffinity;
        else {
            log("could not get process affinity mask -> not setting");
            return 0;
        }
    }

    /**
     * Gets the priority flag.
     * 
     * @return the priority flag
     */
    private int getPriorityFlag() {
        switch (_priority) {
        case PRIORITY_NORMAL:
            return MyKernel32.NORMAL_PRIORITY_CLASS;
        case PRIORITY_ABOVE_NORMAL:
            return MyKernel32.ABOVE_NORMAL_PRIORITY_CLASS;
        case PRIORITY_HIGH:
            return MyKernel32.HIGH_PRIORITY_CLASS;
        case PRIORITY_BELOW_NORMAL:
            return MyKernel32.BELOW_NORMAL_PRIORITY_CLASS;
        case PRIORITY_LOW:
            return MyKernel32.IDLE_PRIORITY_CLASS;
        default:
            return 0;
        }
    }

    // fd.handle = pointer.peer, using reflection, since both are private
    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#waitFor()
     */
    public void waitFor() {
        if (!isRunning())
            return;
        waitFor(MyKernel32.INFINITE);
    }

    /**
     * Gets the exit code internal.
     * 
     * @return the exit code internal
     */
    private int getExitCodeInternal() {
        IntByReference code = new IntByReference();
        if (_processInformation == null)
            return -1;
        boolean result = MyKernel32.INSTANCE.GetExitCodeProcess(_processInformation.hProcess, code);
        try {
            // if server overloaded windows may need some time to set the exit code.
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // System.out.println("get exit code internal " + result + " " + code.getValue());
        if (result) {
            //log("GetExitCodeProcess code "+code.getValue());
            return code.getValue();
        } else {
            //log("GetExitCodeProcess "+MyKernel32.INSTANCE.GetLastError());
            return -3;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#waitFor(int)
     */
    public void waitFor(long timeout) {
        if (!isRunning())
            return;
        if (timeout > Integer.MAX_VALUE)
            timeout = Integer.MAX_VALUE;
        if (_processInformation == null)
            return;
        int result = MyKernel32.INSTANCE.WaitForSingleObject(_processInformation.hProcess, (int) timeout);

    }

    private String getSystemError(int code) {
        Kernel32 lib = Kernel32.INSTANCE;
        PointerByReference pref = new PointerByReference();
        lib.FormatMessage(Kernel32.FORMAT_MESSAGE_ALLOCATE_BUFFER | Kernel32.FORMAT_MESSAGE_FROM_SYSTEM
                | Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS, null, code, 0, pref, 0, null);
        String s = pref.getValue().getString(0, !Boolean.getBoolean("w32.ascii"));
        s = s.replace(".\r", ".").replace(".\n", ".");
        lib.LocalFree(pref.getValue());
        return s;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#stop(int, int)
     */
    public boolean stop(int timeout, int code) {
        if (_pid <= 0) {
            log("cannot kill process with pid " + _pid);
            return false;
        }
        // first try polite kill
        // e.g. post WM_CLOSE to all windows whose PID
        // matches our process.
        MyUser32.WNDENUMPROC closeWindow = new MyUser32.WNDENUMPROC() {
            // lParam is the pid of our process
            public boolean callback(Pointer wnd, int lParam) {
                // get the pid of the window
                IntByReference dwID = new IntByReference();
                MyUser32.INSTANCE.GetWindowThreadProcessId(wnd, dwID);
                // if this windows belongs to our process
                if (dwID.getValue() == lParam) {
                    //System.out.println("post message a: " + wnd);
                    MyUser32.INSTANCE.PostMessageA(wnd, MyUser32.WM_CLOSE, null, null);
                    // MyUser32.INSTANCE.PostMessageA(wnd, MyUser32.WM_QUIT,
                    // null, null) ;
                    // MyUser32.INSTANCE.PostMessageA(wnd, MyUser32.WM_DESTROY,
                    // null, null) ;
                }
                // continue with next window
                return true;
            }
        };
        // execute closeWindow on all windows
        MyUser32.INSTANCE.EnumWindows(closeWindow, _pid);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

        // Wait for process to terminate

        if (timeout > 0)
            waitFor(timeout);

        // give system time to put exit code
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // If still running -> hard kill
        if (isRunning()) {
            log("process is not polite -> hard kill");
            return kill(code);
        } else {
            //_processInformation = null;
            _pid = -1;
            setExitCode(code);
            return true;
        }
    }

    // public boolean cleanKill(int code, int timeout)
    // {
    // // first try polite kill
    // // e.g. post WM_CLOSE to all windows whose PID
    // // matches our process.
    // MyUser32.WNDENUMPROC closeWindow = new MyUser32.WNDENUMPROC()
    // {
    // // lParam is the pid of our process
    // public boolean callback(Pointer wnd, int lParam)
    // {
    // // get the pid of the window
    // IntByReference dwID = new IntByReference();
    // MyUser32.INSTANCE.GetWindowThreadProcessId(wnd, dwID) ;
    // // if this windows belongs to our process
    // if(dwID.getValue() == lParam)
    // {
    // MyUser32.INSTANCE.PostMessageA(wnd, MyUser32.WM_CLOSE, null, null) ;
    // }
    // // continue with next window
    // return true;
    // }
    // };
    // // execute closeWindow on all windows
    // MyUser32.INSTANCE.EnumWindows(closeWindow ,
    // _pid) ;
    //
    // // Wait for process to terminate
    // waitFor(timeout);
    // // If still running -> hard kill
    // if (isRunning())
    // return kill(code);
    // return false;
    //
    // }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#kill(int)
     */
    public boolean kill(int code) {
        boolean result = false;
        try {
            if (_pid <= 0) {
                log("cannot kill process with pid " + _pid);
                return false;
            }

            if (!isRunning()) {
                // _processInformation = null;
                _pid = -1;
                return false;
            }
            int i = 0;
            if (_processInformation != null && _processInformation.hProcess != Pointer.NULL)
                while (!result && i < 10) {
                    if (_processInformation != null && _processInformation.hProcess != Pointer.NULL) {
                        result = MyKernel32.INSTANCE.TerminateProcess(_processInformation.hProcess, code);
                        if (!result) {
                            log("kill failed: " + _pid + " error " + MyKernel32.INSTANCE.GetLastError());
                            i++;
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                                Thread.currentThread().interrupt();
                            }

                        }
                    } else {
                        Thread.sleep(1000);
                        result = !isRunning();
                    }

                }
            Thread.sleep(100);
            if (!isRunning())
                _pid = -1;
        } catch (Exception ex) {
            ex.printStackTrace();
            result = true;
        }

        if (!result)
            log("kill failed: " + _pid + " process still running");

        return result;
    }

    /**
     * Kill.
     * 
     * @param pid
     *            the pid
     * @param code
     *            the code
     * 
     * @return true, if successful
     */
    public static boolean kill(int pid, int code) {
        if (pid <= 0)
            return false;
        Pointer hProcess = MyKernel32.INSTANCE.OpenProcess(MyKernel32.PROCESS_TERMINATE, false, pid);
        boolean result = MyKernel32.INSTANCE.TerminateProcess(hProcess, code);
        Thread.yield();
        if (!result)
            System.out.println("kill failed: " + pid);
        MyKernel32.INSTANCE.CloseHandle(hProcess);
        return result;
    }

    /**
     * Gets the process maps.
     * 
     * @param pid
     *            the pid
     * 
     * @return the process maps
     */
    public static Map[] getProcessMaps(int pid) {
        Map processMap = new HashMap();
        Map childrenMap = new MultiHashMap();
        Map[] result = new Map[] { processMap, childrenMap };

        Pointer processes = MyKernel32.INSTANCE.CreateToolhelp32Snapshot(MyKernel32.TH32CS_SNAPPROCESS, 0);
        if (processes == null) {
            System.out.println("task list empty ");
            return result;
        }

        PROCESSENTRY32 me = new PROCESSENTRY32();
        me.szExeFile = new char[MyKernel32.MAX_PATH];
        int size = me.size();
        // System.out.println("size: " + size);
        me.dwSize = size;
        if (MyKernel32.INSTANCE.Process32First(processes, me)) {
            do {
                //System.out.println(/* new String(next.szExeFile) + */" " + me.th32ModuleID + " " + me.th32DefaultHeapID + " " + me.th32ProcessID
                //      + " -> " + me.th32ParentProcessID);
                if (me.th32ProcessID > 0)
                    processMap.put(new Integer(me.th32ProcessID), me);
                if (me.th32ParentProcessID > 0 && processMap.get(new Integer(me.th32ParentProcessID)) != null) {
                    childrenMap.put(new Integer(me.th32ParentProcessID), new Integer(me.th32ProcessID));
                }
                // else
                // System.out.println("not added");

            } while (MyKernel32.INSTANCE.Process32Next(processes, me));
        } else
            System.out.println("cannot access first process in list ");

        MyKernel32.INSTANCE.CloseHandle(processes);

        return result;
    }

    /** The levels. */
    int levels;

    /** The _pf counter. */
    private PdhCounter _pfCounter;

    /** The _v mem counter. */
    private PdhCounter _vMemCounter;

    /** The _cpu counter. */
    private PdhCounter _cpuCounter;

    /** The _p mem counter. */
    private PdhCounter _pMemCounter;

    private PdhCounter _threadCounter;
    private PdhCounter _handleCounter;

    private boolean _started = false;

    /**
     * Gets the process tree.
     * 
     * @param pid
     *            the pid
     * 
     * @return the process tree
     */
    static public List getProcessTree(int pid) {
        Map[] maps = getProcessMaps(pid);
        Map processMap = maps[0];
        Map childrenMap = maps[1];
        Collection pids = new ArrayList();
        pids.add(new Integer(pid));
        return getProcessTree(childrenMap, pids);
    }

    /**
     * Gets the process tree.
     * 
     * @param childrenMap
     *            the children map
     * @param pids
     *            the pids
     * 
     * @return the process tree
     */
    static List getProcessTree(Map childrenMap, Collection pids) {
        List result = new ArrayList();
        if (pids == null)
            return result;
        if (pids.isEmpty())
            return result;
        for (Iterator it = pids.iterator(); it.hasNext();) {
            Integer i = (Integer) it.next();
            // System.out.println(i);
            result.addAll(getProcessTree(childrenMap, (Collection) childrenMap.get(i)));
        }
        result.addAll(pids);
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#killTree(int)
     */
    public boolean killTree(int code) {
        if (_pid <= 0) {
            log("cannot kill process with pid " + _pid);
            return false;
        }

        if (!isRunning())
            return false;
        boolean result = true;
        List tree = getProcessTree(_pid);
        int retry = 0;
        while (tree.size() < 2 && retry < 20) {
            //System.out.println("retry " + retry++);
            tree = getProcessTree(_pid);
        }
        for (Iterator it = tree.iterator(); it.hasNext();) {
            int pid = ((Integer) it.next()).intValue();
            if (pid != _pid)
                result = result && kill(pid, code);

        }

        result = result && kill(code);

        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.AbstractProcess#getExitCode()
     */
    @Override
    public int getExitCode() {
        int result = 0;
        if (_exitCode < 0 && _processInformation != null) {
            result = getExitCodeInternal();
            if (result != MyKernel32.STILL_ACTIVE)
                setExitCode(result);
            else
                setExitCode(-2);
        } else {
            //log("getExitCode "+_exitCode + " "+_processInformation);
        }
        //System.out.println("get exit code "+_exitCode);
        return _exitCode;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#isRunning()
     */
    public boolean isRunning() {
        if (_pid <= 0) {
            //log("is running: false "+_pid);
            return false;
        }
        if (_processInformation == null)
            return false;
        // return _processInformation != null && getExitCode() < 0 && _pid > 0;
        boolean result = getExitCode() == -2 && _pid >= 0;
        //log("is running: "+result +" "+_pid + " "+ _exitCode);
        return result;
        /*
        Pointer process = MyKernel32.INSTANCE.OpenProcess(MyKernel32.PROCESS_QUERY_INFORMATION, false, _pid);
        if (process == Pointer.NULL)
        {
           log("is running: false "+_pid);
           return false;
        }
        MyKernel32.INSTANCE.CloseHandle(process);
        log("is running: true "+_pid);
        return true;
        */

    }

    // if you use counters: you will have to destroy before finalze is called.
    // Otherwise the JVM may crash
    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#destroy()
     */
    volatile boolean destroyed = false;

    public void destroy() {
        if (destroyed)
            return;
        destroyed = true;
        if (_processInformation != null) {
            if (_teeName != null && _inputStream != null) {
                try {
                    _inputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    _outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    _errorStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                _inputStream = null;
                _outputStream = null;
                _errorStream = null;
                new File(_tmpPath, "in_" + _teeName).delete();
                new File(_tmpPath, "out_" + _teeName).delete();
                new File(_tmpPath, "err_" + _teeName).delete();

            }
            //else
            //System.out.println("no streams to destroy");

            if (outRead != null && outRead.getValue() != Pointer.NULL) {
                MyKernel32.INSTANCE.SetHandleInformation(outRead.getValue(), 2, 0);
                MyKernel32.INSTANCE.CloseHandle(outRead.getValue());
                outRead = null;
            }

            if (errRead != null && errRead.getValue() != Pointer.NULL) {
                MyKernel32.INSTANCE.SetHandleInformation(errRead.getValue(), 2, 0);
                MyKernel32.INSTANCE.CloseHandle(errRead.getValue());
                errRead = null;
            }

            if (inWrite != null && inWrite.getValue() != Pointer.NULL) {
                MyKernel32.INSTANCE.SetHandleInformation(inWrite.getValue(), 2, 0);
                MyKernel32.INSTANCE.CloseHandle(inWrite.getValue());
                inWrite = null;
            }

            if (_processInformation.hThread != null)
                if (!_processInformation.hThread.equals(Pointer.NULL))
                    MyKernel32.INSTANCE.CloseHandle(_processInformation.hThread);
            if (_processInformation.hProcess != null)
                if (!_processInformation.hProcess.equals(Pointer.NULL))
                    MyKernel32.INSTANCE.CloseHandle(_processInformation.hProcess);
            if (_cpuCounter != null) {
                _cpuCounter.close();
                _cpuCounter = null;
            }
            if (_vMemCounter != null) {
                _vMemCounter.close();
                _vMemCounter = null;
            }
            if (_pMemCounter != null) {
                _pMemCounter.close();
                _pMemCounter = null;
            }

            if (_pfCounter != null) {
                _pfCounter.close();
                _pfCounter = null;
            }
            if (_threadCounter != null) {
                _threadCounter.close();
                _threadCounter = null;
            }
            if (_handleCounter != null) {
                _handleCounter.close();
                _handleCounter = null;
            }
        }
        log("process destroyed " + _pid);
        _processInformation = null;

        _startupInfo = null;
        /*
         * if (_pipeStreams) { if (inRead != null) if (inRead.getValue() !=
         * null) MyKernel32.INSTANCE.CloseHandle(inRead.getValue()); if
         * (outWrite != null) if (outWrite.getValue() != null)
         * MyKernel32.INSTANCE.CloseHandle(outWrite.getValue()); if (errWrite !=
         * null) if (errWrite.getValue() != null)
         * MyKernel32.INSTANCE.CloseHandle(errWrite.getValue()); }
         * 
         * if (_outputStream != null) { try { _outputStream.close(); } catch
         * (IOException e) { } _outputStream = null; }
         * 
         * if (_errorStream != null) { try { _errorStream.close(); } catch
         * (IOException e) { } _errorStream = null; }
         * 
         * if (_inputStream != null) { try { _inputStream.close(); } catch
         * (IOException e) { } _inputStream = null; }
         */

    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#finalize()
     */
    @Override
    public void finalize() throws Throwable {
        try {
            // this may cause jvm crash when java shuts down -> TODO
            //destroy();
        } finally {
            super.finalize();
        }
    }

    /**
     * Read virtual memory to structure.
     * 
     * @param baseAddress
     *            the base address
     * @param goal
     *            the goal
     * 
     * @return true, if successful
     */
    boolean readVirtualMemoryToStructure(Pointer baseAddress, Structure goal) {
        int size = goal.size();
        // System.out.println("readVirtualMemoryToStructure "+size);
        int ret = Ntdll.INSTANCE.ZwReadVirtualMemory(_processInformation.hProcess, baseAddress, goal.getPointer(),
                size, null);
        if (ret != 0)
            log("pid " + _pid + " ZwReadVirtualMemory returns " + Integer.toHexString(ret));

        goal.read();
        return ret == 0;

    }

    /**
     * Read virtual memory to memory.
     * 
     * @param baseAddress
     *            the base address
     * @param goal
     *            the goal
     * 
     * @return true, if successful
     */
    boolean readVirtualMemoryToMemory(Pointer baseAddress, Memory goal) {
        int size = (int) goal.getSize();
        // System.out.println("readVirtualMemoryToMemory "+size);
        int ret = Ntdll.INSTANCE.ZwReadVirtualMemory(_processInformation.hProcess, baseAddress, goal, size, null);
        if (ret != 0)
            log("pid " + _pid + " ZwReadVirtualMemory returns " + Integer.toHexString(ret));

        return ret == 0;

    }

    /**
     * Gets the command line internal. this works only for 32 bit processes
     * 
     * @return the command line internal
     */
    String getCommandLineInternal() {
        // System.out.println("get command internal "+getPid());
        String result = "?";
        PROCESS_BASIC_INFORMATION pbi = null;

        pbi = new PROCESS_BASIC_INFORMATION();
        IntByReference returnLength = new IntByReference();
        Pointer hProcess = _processInformation.hProcess;
        int size = pbi.size();
        int ret = Ntdll.INSTANCE.ZwQueryInformationProcess(hProcess, (byte) 0, pbi.getPointer(), size,
                returnLength);
        if (ret == 0) {
            pbi.read();
            if (pbi.PebBaseAddress != null) {
                PEB peb = new PEB();
                // System.out.println(""+1);
                if (readVirtualMemoryToStructure(pbi.PebBaseAddress, peb))
                    if (peb.ProcessParameters != null) {
                        RTL_USER_PROCESS_PARAMETERS userParams = new RTL_USER_PROCESS_PARAMETERS();
                        // System.out.println(""+2);
                        if (readVirtualMemoryToStructure(peb.ProcessParameters, userParams)) {
                            // System.out.println("MaximumLength "+userParams.CommandLine.MaximumLength);
                            if (userParams.CommandLine.MaximumLength > 0) {
                                Memory stringBuffer = new Memory(userParams.CommandLine.MaximumLength);
                                // System.out.println(""+3);
                                if (readVirtualMemoryToMemory(userParams.CommandLine.Buffer, stringBuffer))
                                    result = stringBuffer.getString(0, true);
                            }
                            // System.out.println("MaximumLength "+userParams.CommandLine.MaximumLength);
                            if (userParams.CurrentDirectoryPath.MaximumLength > 0) {
                                Memory stringBuffer = new Memory(userParams.CurrentDirectoryPath.MaximumLength);
                                if (readVirtualMemoryToMemory(userParams.CurrentDirectoryPath.Buffer, stringBuffer))
                                    _workingDir = stringBuffer.getString(0, true);
                            }
                            if (userParams.WindowTitle.MaximumLength > 0) {
                                Memory stringBuffer = new Memory(userParams.WindowTitle.MaximumLength);
                                if (readVirtualMemoryToMemory(userParams.WindowTitle.Buffer, stringBuffer))
                                    _title = stringBuffer.getString(0, true);
                            }
                            if (userParams.Environment != null) {
                                // get size of environment strings
                                MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION();
                                int ll = MyKernel32.INSTANCE.VirtualQueryEx(hProcess, userParams.Environment,
                                        memInfo.getPointer(), memInfo.size());
                                memInfo.read();
                                if (ll == 0) {
                                    _logger.warning(
                                            "error getting environment in VirtualQueryEx " + Native.getLastError());
                                } else if (MyKernel32.PAGE_NOACCESS == memInfo.Protect
                                        || MyKernel32.PAGE_EXECUTE == memInfo.Protect) {
                                    _logger.warning("error getting environment in VirtualQueryEx no access right");
                                } else {

                                    Memory mem = new Memory(memInfo.RegionSize);
                                    readVirtualMemoryToMemory(userParams.Environment, mem);

                                    List<String> envStrings = new ArrayList<String>();

                                    String env = null;
                                    int l = 0;
                                    while (!"".equals(env)) {
                                        env = mem.getString(l, true);
                                        if (env != null && env.length() != 0) {
                                            envStrings.add(env);
                                            l += env.length() * 2 + 2;
                                        }
                                        if (env == null)
                                            break;
                                    }

                                    parseEnvString(envStrings);
                                }
                            }
                        }

                    }
            }
        }
        // else
        // System.out.println("3 pid " + _pid +
        // " ZwQueryInformationProcess returns " + Integer.toHexString(ret));
        if (result != null)
            result = result.trim();
        return result;

    }

    private void parseEnvString(List<String> envStrings) {
        if (envStrings == null || envStrings.size() == 0)
            return;
        for (String str : envStrings) {
            String[] var = str.split("=");
            if (var.length == 2)
                _environment.put(var[0], var[1]);
        }

    }

    // this will work only if we run on 64.
    // if we run on wow64 (eg 32 bit), ZwQueryInformationProcess returns 0, but
    // PEB64.ProcessParameters is empty
    String getCommandLineInternal64() {
        log("get command internal 64 " + getPid());
        String result = "?";
        PROCESS_BASIC_INFORMATION pbi = null;

        pbi = new PROCESS_BASIC_INFORMATION();
        IntByReference returnLength = new IntByReference();
        Pointer hProcess = _processInformation.hProcess;
        int size = pbi.size();
        int ret = Ntdll.INSTANCE.ZwQueryInformationProcess(hProcess, (byte) 0, pbi.getPointer(), size,
                returnLength);
        if (ret == 0) {
            pbi.read();
            if (pbi.PebBaseAddress != null) {
                PEB64 peb = new PEB64();
                //System.out.println("64 " + 1);
                if (readVirtualMemoryToStructure(pbi.PebBaseAddress, peb))
                    if (peb.ProcessParameters != null) {
                        RTL_USER_PROCESS_PARAMETERS userParams = new RTL_USER_PROCESS_PARAMETERS();
                        //System.out.println("64 " + 2);
                        if (readVirtualMemoryToStructure(peb.ProcessParameters, userParams)) {
                            //System.out.println("MaximumLength " + userParams.CommandLine.MaximumLength);
                            //System.out.println("Length " + userParams.CommandLine.Length);
                            Memory stringBuffer = new Memory(userParams.CommandLine.Length);
                            //System.out.println("64 " + 3);
                            if (readVirtualMemoryToMemory(userParams.CommandLine.Buffer, stringBuffer))
                                result = stringBuffer.getString(0, true);
                        }

                    }
            }
        } else
            log("pid " + _pid + " ZwQueryInformationProcess returns " + Integer.toHexString(ret));
        return result;

    }

    // this should run on all platforms
    // TODO optimize by calling windows methods for WMI
    // note: Runtime.exec("cmd /C wmic") hangs
    // note: we cannot use p.getInputStream() since the result stream contains
    // unexpeced characters
    // note: when we write the result to file we have to convert the string.
    public String getCommandLineInternalWMI() {
        String result = "?";
        // if the server is overloaded we may not get an answer -> try 3 times
        for (int k = 0; k < 3 && "?".equals(result); k++)
            try {

                WindowsXPProcess p = new WindowsXPProcess();
                new File("wmic.tmp").delete();
                p.setCommand("cmd /C wmic process where processid=" + getPid() + " get commandline > wmic.tmp");
                p.setVisible(false);
                p.start();
                p.waitFor(30000);
                BufferedReader br = new BufferedReader(new FileReader("wmic.tmp"));
                br.readLine();
                br.readLine();
                String l = br.readLine();
                if (l.codePointAt(0) == 0) {
                    StringBuffer s = new StringBuffer();
                    for (int i = 0; i < l.length(); i++)
                        if (l.codePointAt(i) != 0)
                            s.append(l.charAt(i));
                    l = s.toString();
                }
                br.close();
                result = l;
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                    return result;
                }
            }
        return result;

    }

    /**
     * Gets the total cpu.
     * 
     * @return the total cpu
     */
    public long getTotalCPU() {
        long result = -1;
        if (!isRunning())
            return -1;
        LongByReference lpCreationTime = new LongByReference();
        LongByReference lpExitTime = new LongByReference();
        LongByReference lpKernelTime = new LongByReference();
        LongByReference lpUserTime = new LongByReference();

        if (MyKernel32.INSTANCE.GetProcessTimes(_processInformation.hProcess, lpCreationTime, lpExitTime,
                lpKernelTime, lpUserTime))
            result = lpUserTime.getValue() + lpKernelTime.getValue();
        return result;
    }

    /**
     * Current process id.
     * 
     * @return the int
     */
    public static int currentProcessId() {
        return MyKernel32.INSTANCE.GetCurrentProcessId();
    }

    /**
     * Process id of active window.
     * 
     * @return the int
     */
    public static int processIdOfActiveWindow() {
        Pointer w = MyUser32.INSTANCE.GetForegroundWindow();
        IntByReference result = new IntByReference();
        MyUser32.INSTANCE.GetWindowThreadProcessId(w, result);
        return result.getValue();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#getCurrentCpu()
     */
    public int getCurrentCpu() {
        if (!isRunning() || getCpuCounter() == null)
            return -1;
        PdhCounter c = getCpuCounter();
        return c.getIntValue();
    }

    /**
     * Gets the cpu counter.
     * 
     * @return the cpu counter
     */
    private PdhCounter getCpuCounter() {
        if (_cpuCounter == null)
            _cpuCounter = Pdh.getProcessEnglishCounter(_pid, "% Processor Time");
        return _cpuCounter;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#getCurrentPhysicalMemory()
     */
    public int getCurrentPhysicalMemory() {
        if (!isRunning())
            return -1;
        PdhCounter c = getPMemCounter();
        return c.getIntValue();
    }

    /**
     * Gets the p mem counter.
     * 
     * @return the p mem counter
     */
    private PdhCounter getPMemCounter() {
        if (_pMemCounter == null)
            _pMemCounter = Pdh.getProcessEnglishCounter(_pid, "Private Bytes");
        return _pMemCounter;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#getCurrentVirtualMemory()
     */
    public int getCurrentVirtualMemory() {
        if (!isRunning() || getVMemCounter() == null)
            return -1;
        PdhCounter c = getVMemCounter();
        return c.getIntValue();
    }

    /**
     * Gets the v mem counter.
     * 
     * @return the v mem counter
     */
    private PdhCounter getVMemCounter() {
        if (_vMemCounter == null)
            _vMemCounter = Pdh.getProcessEnglishCounter(_pid, "Virtual Bytes");
        return _vMemCounter;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#getCurrentPageFaults()
     */
    public int getCurrentPageFaults() {
        if (!isRunning())
            return -1;
        PdhCounter c = getPfCounter();
        return c.getIntValue();
    }

    /**
     * Gets the pf counter.
     * 
     * @return the pf counter
     */
    private PdhCounter getPfCounter() {
        if (_pfCounter == null)
            _pfCounter = Pdh.getProcessEnglishCounter(_pid, "Page Faults/sec");
        return _pfCounter;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rzo.yajsw.os.Process#getChildren()
     */
    public Collection getChildren() {
        return getProcessTree(_pid);
    }

    // test
    /**
     * The main method.
     * 
     * @param args
     *            the arguments
     */
    public static void main(String[] args) {
        /*
         * WindowsXPProcess[] p = new WindowsXPProcess[1]; for (int i = 0; i <
         * p.length; i++) { p[i] = new WindowsXPProcess(); //
         * p[i].setPipeStreams(true, false);
         * p[i].setCommand("ping 127.0.0.1 -t");// "c:/driwin/dripc.exe");// //
         * "java -cp yajsw.jar // org.rzo.yajsw.HelloWorld > // t.log"); //
         * p[i].setWorkingDir("c:/driwin"); p[i].setVisible(false);
         * p[i].setPipeStreams(true, false); } boolean done = false; while
         * (!done) { done = true; System.out.println("START");
         * 
         * for (int i = 0; i < p.length; i++) {
         * 
         * p[i].start(); //
         * System.out.println(p[i].getCommandLineInternalWMI());
         * 
         * / String line = null; int k = 0; try { InputStreamReader isr = new
         * InputStreamReader(p[i].getInputStream()); BufferedReader br = new
         * BufferedReader(isr);
         * 
         * line = br.readLine(); System.out.println(line); while (k < 30 && line
         * != null) { System.out.println(line); line = br.readLine(); k++; }
         * 
         * } catch (Exception e) { // TODO Auto-generated catch block
         * e.printStackTrace(); } /
         * 
         * System.out.println("sleep"); p[i].waitFor(5000); }
         * 
         * System.out.println("KILL"); for (int i = 0; i < p.length; i++) { //
         * p[i].killTree(999); ((WindowsXPProcess) p[i]).stop(5000, 999);
         * System.out.println(p[i].getExitCode()); // p[i].finalize(); } try {
         * Thread.sleep(1000); } catch (InterruptedException e) { // TODO
         * Auto-generated catch block e.printStackTrace(); } }
         * 
         * // p.setCommand("java -classpath z:\dev\yajsw\wrapper.jar org.rzo." )
         */
        /*
        WindowsXPProcess p = new WindowsXPProcess();
        p.setCommand("notepad");
        p.setUser("test\\yajsw");
        p.setPassword("yajsw");
        p.start();
        */
        getProcess(3332);

    }

    /**
     * Reconnect streams.
     * 
     * @return true, if successful
     */
    public boolean reconnectStreams() {
        if (_teeName != null)
            try {
                _inputStream = new CyclicBufferFileInputStream(new File(_tmpPath, "out_" + _teeName));
                _errorStream = new CyclicBufferFileInputStream(new File(_tmpPath, "err_" + _teeName));
                _outputStream = new CyclicBufferFilePrintStream(new File(_tmpPath, "in_" + _teeName));
                return true;
            } catch (Exception ex) {
                ex.printStackTrace();
            }

        return false;

    }

    /**
     * Writefd.
     * 
     * @param fd
     *            the fd
     * @param pointer
     *            the pointer
     */
    private void writefd(FileDescriptor fd, Pointer pointer) {
        try {
            // Field[] fields = FileDescriptor.class.getDeclaredFields();
            // System.out.println("fields");
            // for (Field field : fields){
            // System.out.println(field.getName());
            // }
            // System.out.println("writefd");
            Field handleField = FileDescriptor.class.getDeclaredField("handle");
            handleField.setAccessible(true);
            Field peerField = Pointer.class.getDeclaredField("peer");
            peerField.setAccessible(true);
            long value = peerField.getLong(pointer);
            // System.out.println(value);
            // System.out.flush();
            handleField.setLong(fd, value);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public String currentUser() {
        String result = System.getenv("USERDOMAIN") + "\\" + System.getenv("USERNAME");
        result = result.toUpperCase();
        return result;
    }

    public String currentUserName() {
        String result = System.getProperty("user.name");
        if (result == null)
            return "";
        result = result.toUpperCase();
        return result;
    }

    public String currentUserDomain() {
        String result = System.getenv("USERDOMAIN");
        if (result == null)
            return "";
        return result.toUpperCase();
    }

    public String standardizeUser(String user) {
        if (user == null)
            return null;
        if (user.indexOf("\\") == -1)
            return currentUserDomain() + "\\" + user.toUpperCase();
        return user.toUpperCase();
    }

    boolean doesUserHavePrivilege(String lpPrivilegeName)

    {
        PointerByReference hToken = new PointerByReference();
        IntByReference dwSize = new IntByReference();
        Memory lpPrivileges;
        MyAdvapi.LUID PrivilegeLuid = new MyAdvapi.LUID();
        int i;
        boolean bResult = false;

        if (!MyAdvapi.INSTANCE.OpenProcessToken(MyKernel32.INSTANCE.GetCurrentProcess(),
                MyAdvapi.INSTANCE.TOKEN_QUERY, hToken))
            return false;

        MyAdvapi.INSTANCE.GetTokenInformation(hToken.getValue(), MyAdvapi.TokenPrivileges, null, 0, dwSize);

        lpPrivileges = new Memory(dwSize.getValue());

        if (!MyAdvapi.INSTANCE.GetTokenInformation(hToken.getValue(), MyAdvapi.TokenPrivileges, lpPrivileges,
                dwSize.getValue(), dwSize)) {
            return false;
        }

        MyKernel32.INSTANCE.CloseHandle(hToken.getValue());

        if (!MyAdvapi.INSTANCE.LookupPrivilegeValueA(null, lpPrivilegeName, PrivilegeLuid)) {
            return false;
        }

        MyAdvapi.TOKEN_PRIVILEGES privileges = new MyAdvapi.TOKEN_PRIVILEGES(lpPrivileges);
        for (i = 0; i < privileges.PrivilegeCount; i++) {
            if (privileges.Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart
                    && privileges.Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart) {
                return true;
            }
        }
        return false;
    }

    public int getCurrentHandles() {
        if (!isRunning() || getHandlesCounter() == null)
            return -1;
        PdhCounter c = getHandlesCounter();
        return c.getIntValue();
    }

    private PdhCounter getHandlesCounter() {
        if (_handleCounter == null)
            _handleCounter = Pdh.getProcessEnglishCounter(_pid, "Handle Count");
        return _handleCounter;
    }

    public int getCurrentThreads() {
        if (!isRunning() || getThreadsCounter() == null)
            return -1;
        PdhCounter c = getThreadsCounter();
        return c.getIntValue();
    }

    private PdhCounter getThreadsCounter() {
        if (_threadCounter == null)
            _threadCounter = Pdh.getProcessEnglishCounter(_pid, "Thread Count");
        return _threadCounter;
    }

    public boolean isTerminated() {
        return (_started && !isRunning());
    }

    public static boolean setWorkingDirectory(String name) {
        File f = new File(name);
        String dir;
        if (!f.exists() || !f.isDirectory()) {
            System.out.println("setWorkingDirectory failed. file not found " + name);
            return false;
        } else
            try {
                dir = f.getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        boolean result = MyKernel32.INSTANCE.SetCurrentDirectoryA(dir);
        if (result)
            System.setProperty("user.dir", dir);
        return result;
    }

}