protected virtual void Dispose()
        {
            if (_dataHandle.IsAllocated)
            {
                _dataHandle.Free();
            }

            if (_initialized)
            {
                _dllEntry?.Invoke(_codeBase, DllReason.DLL_PROCESS_DETACH, null);
                _initialized = false;
            }

            if (_modules.Count > 0)
            {
                foreach (HCoustomMudule module in _modules)
                {
                    if (!InvalidHandle(module)) // INVALID_HANDLE
                    {
                        Win.FreeLibrary(module);
                    }
                }
            }

            if (_codeBase != null)
            {
                Win.VirtualFree(_codeBase, 0, AllocationType.RELEASE);
            }

            Disposed = true;
        }
        private void FinalizeSection(SectionFinalizeData sectionData)
        {
            uint protect, oldProtect;
            int  executable;
            int  readable;
            int  writeable;

            if (sectionData.Size == 0)
            {
                return;
            }

            if ((sectionData.Characteristics & Win.IMAGE_SCN_MEM_DISCARDABLE) > 0)
            {
                // section is not needed any more and can safely be freed
                if (sectionData.Address == sectionData.AlignedAddress &&
                    (sectionData.Last ||
                     _headers->OptionalHeader.SectionAlignment == _pageSize ||
                     (sectionData.Size % _pageSize) == 0)
                    )
                {
                    // Only allowed to decommit whole pages
                    Win.VirtualFree(sectionData.Address, sectionData.Size, AllocationType.DECOMMIT);
                }
                return;
            }

            // determine protection flags based on characteristics
            executable = (sectionData.Characteristics & (uint)ImageSectionFlags.IMAGE_SCN_MEM_EXECUTE) != 0 ? 1 : 0;
            readable   = (sectionData.Characteristics & (uint)ImageSectionFlags.IMAGE_SCN_MEM_READ) != 0 ? 1 : 0;
            writeable  = (sectionData.Characteristics & (uint)ImageSectionFlags.IMAGE_SCN_MEM_WRITE) != 0 ? 1 : 0;
            protect    = (uint)ProtectionFlags[executable, readable, writeable];
            if ((sectionData.Characteristics & Win.IMAGE_SCN_MEM_NOT_CACHED) > 0)
            {
                protect |= Win.PAGE_NOCACHE;
            }

            // change memory access flags
            if (!Win.VirtualProtect(sectionData.Address, sectionData.Size, protect, out oldProtect))
            {
                throw new NativeDllLoadException("Error protecting memory page");
            }
        }