public void Dispose()
    {
        if (_initialized)
        {
            if (_dllEntry != null)
            {
                _dllEntry.Invoke(pCode, DllReason.DLL_PROCESS_DETACH, IntPtr.Zero);
            }
            _initialized = false;
        }

        if (ImportModules != null)
        {
            foreach (IntPtr m in ImportModules)
            {
                if (!PtrIsInvalidHandle(m))
                {
                    Win.FreeLibrary(m);
                }
            }
            ImportModules = null;
        }

        if (pCode != IntPtr.Zero)
        {
            Win.VirtualFree(pCode, IntPtr.Zero, AllocationType.RELEASE);
            pCode      = IntPtr.Zero;
            pNTHeaders = IntPtr.Zero;
        }

        Disposed = true;
    }
    static IntPtr[] BuildImportTable(ref IMAGE_NT_HEADERS OrgNTHeaders, IntPtr pCode)
    {
        System.Collections.Generic.List <IntPtr> ImportModules = new System.Collections.Generic.List <IntPtr>();
        uint   NumEntries  = OrgNTHeaders.OptionalHeader.ImportTable.Size / Sz.IMAGE_IMPORT_DESCRIPTOR;
        IntPtr pImportDesc = PtrAdd(pCode, OrgNTHeaders.OptionalHeader.ImportTable.VirtualAddress);

        for (uint i = 0; i != NumEntries; i++, pImportDesc = PtrAdd(pImportDesc, Sz.IMAGE_IMPORT_DESCRIPTOR))
        {
            IMAGE_IMPORT_DESCRIPTOR ImportDesc = PtrRead <IMAGE_IMPORT_DESCRIPTOR>(pImportDesc);
            if (ImportDesc.Name == 0)
            {
                break;
            }

            IntPtr handle = Win.LoadLibrary(PtrAdd(pCode, ImportDesc.Name));
            if (PtrIsInvalidHandle(handle))
            {
                foreach (IntPtr m in ImportModules)
                {
                    Win.FreeLibrary(m);
                }
                ImportModules.Clear();
                throw new DllException("Can't load libary " + Marshal.PtrToStringAnsi(PtrAdd(pCode, ImportDesc.Name)));
            }
            ImportModules.Add(handle);

            IntPtr pThunkRef, pFuncRef;
            if (ImportDesc.OriginalFirstThunk > 0)
            {
                pThunkRef = PtrAdd(pCode, ImportDesc.OriginalFirstThunk);
                pFuncRef  = PtrAdd(pCode, ImportDesc.FirstThunk);
            }
            else
            {
                // no hint table
                pThunkRef = PtrAdd(pCode, ImportDesc.FirstThunk);
                pFuncRef  = PtrAdd(pCode, ImportDesc.FirstThunk);
            }
            for (int SzRef = IntPtr.Size; ; pThunkRef = PtrAdd(pThunkRef, SzRef), pFuncRef = PtrAdd(pFuncRef, SzRef))
            {
                IntPtr ReadThunkRef = PtrRead <IntPtr>(pThunkRef), WriteFuncRef;
                if (ReadThunkRef == IntPtr.Zero)
                {
                    break;
                }
                if (Win.IMAGE_SNAP_BY_ORDINAL(ReadThunkRef))
                {
                    WriteFuncRef = Win.GetProcAddress(handle, Win.IMAGE_ORDINAL(ReadThunkRef));
                }
                else
                {
                    WriteFuncRef = Win.GetProcAddress(handle, PtrAdd(PtrAdd(pCode, ReadThunkRef), Of.IMAGE_IMPORT_BY_NAME_Name));
                }
                if (WriteFuncRef == IntPtr.Zero)
                {
                    throw new DllException("Can't get adress for imported function");
                }
                PtrWrite(pFuncRef, WriteFuncRef);
            }
        }
        return(ImportModules.Count > 0 ? ImportModules.ToArray() : null);
    }