⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 global.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
        {
            /* User is changing flags... check if the memory was discardable */
            if (uFlags & GMEM_DISCARDABLE)
            {
                /* Then set the flag */
                HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
            }
            else
            {
                /* Otherwise, remove the flag */
                HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE;
            }
        }
        else
        {
            /* Otherwise, get the object and check if we have no size */
            Ptr = HandleEntry->Object;
            if (!dwBytes)
            {
                /* Clear the handle and check for a pointer */
                hMem = NULL;
                if (Ptr)
                {
                    /* Make sure the handle isn't locked */
                    if ((uFlags & GMEM_MOVEABLE) && !(HandleEntry->LockCount))
                    {
                        /* Free the current heap */
                        RtlFreeHeap(hProcessHeap, Flags, Ptr);

                        /* Free the handle */
                        HandleEntry->Object = NULL;
                        HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;

                        /* Get the object pointer */
                        hMem = &HandleEntry->Object;
                    }
                }
                else
                {
                    /* Otherwise just return the object pointer */
                    hMem = &HandleEntry->Object;
                }
            }
            else
            {
                /* Otherwise, we're allocating, so set the new flags needed */
                Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
                if (!Ptr)
                {
                    /* We don't have a base, so allocate one */
                    Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
                    BASE_TRACE_ALLOC2(Ptr);
                    if (Ptr)
                    {
                        /* Allocation succeeded, so save our entry */
                        RtlSetUserValueHeap(hProcessHeap,
                                            HEAP_NO_SERIALIZE,
                                            Ptr,
                                            hMem);
                    }
                }
                else
                {
                    /*
                     * If it's not movable or currently locked, we MUST allocate
                     * in-place!
                     */
                    if (!(uFlags & GMEM_MOVEABLE) && (HandleEntry->LockCount))
                    {
                        /* Set the flag */
                        Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
                    }
                    else
                    {
                        /* Otherwise clear the flag if we set it previously */
                        Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;
                    }

                    /* And do the re-allocation */
                    Ptr = RtlReAllocateHeap(hProcessHeap, Flags, Ptr, dwBytes);
                }

                /* Make sure we have a pointer by now */
                if (Ptr)
                {
                    /* Write it in the handle entry and mark it in use */
                    HandleEntry->Object = Ptr;
                    HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE;
                }
                else
                {
                    /* Otherwise we failed */
                    hMem = NULL;
                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                }
            }
        }
    }
    else if (uFlags & GMEM_MODIFY)
    {
        /* This is not a handle-based heap and the caller wants it to be one */
        if (uFlags & GMEM_MOVEABLE)
        {
            /* Get information on its current state */
            Handle = hMem;
            DPRINT1("h h %lx %lx\n", Handle, hMem);
            RtlGetUserInfoHeap(hProcessHeap,
                               HEAP_NO_SERIALIZE,
                               hMem,
                               &Handle,
                               &Flags);
            DPRINT1("h h %lx %lx\n", Handle, hMem);

            /*
             * Check if the handle matches the pointer or if the moveable flag
             * isn't there, which is what we expect since it currenly isn't.
             */
            if (Handle == hMem || !(Flags & BASE_HEAP_FLAG_MOVABLE))
            {
                /* Allocate a handle for it */
                HandleEntry = BaseHeapAllocEntry();

                /* Calculate the size of the current heap */
                dwBytes = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);

                /* Set the movable flag */
                Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;

                /* Now allocate the actual heap for it */
                HandleEntry->Object = RtlAllocateHeap(hProcessHeap,
                                                      Flags,
                                                      dwBytes);
                BASE_TRACE_PTR(HandleEntry->Object, HandleEntry);
                if (!HandleEntry->Object)
                {
                    /*
                     * We failed, manually set the allocate flag and
                     * free the handle
                     */
                    HandleEntry->Flags = RTL_HANDLE_VALID;
                    BaseHeapFreeEntry(HandleEntry);

                    /* For the cleanup case */
                    BASE_TRACE_FAILURE();
                    HandleEntry = NULL;
                    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                }
                else
                {
                    /* Otherwise, copy the current heap and free the old one */
                    RtlMoveMemory(HandleEntry->Object, hMem, dwBytes);
                    RtlFreeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);

                    /* Select the heap pointer */
                    hMem = (HANDLE)&HandleEntry->Object;

                    /* Initialize the count and default flags */
                    HandleEntry->LockCount = 0;
                    HandleEntry->Flags = RTL_HANDLE_VALID |
                                         BASE_HEAP_ENTRY_FLAG_MOVABLE;

                    /* Check if it's also discardable */
                    if (uFlags & GMEM_DISCARDABLE)
                    {
                        /* Set the internal flag */
                        HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
                    }

                    /* Check if it's also DDE Shared */
                    if (uFlags & GMEM_DDESHARE)
                    {
                        /* Set the internal flag */
                        HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
                    }

                    /* Allocation succeeded, so save our entry */
                    RtlSetUserValueHeap(hProcessHeap,
                                        HEAP_NO_SERIALIZE,
                                        HandleEntry->Object,
                                        hMem);
                }
            }
        }
    }
    else
    {
        /* Otherwise, this is a simple RTL Managed Heap, so just call it */
        hMem = RtlReAllocateHeap(hProcessHeap,
                                 Flags | HEAP_NO_SERIALIZE,
                                 hMem,
                                 dwBytes);
        if (!hMem)
        {
            /* Fail */
            BASE_TRACE_FAILURE();
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        }
    }

    /* All done, unlock the heap and return the pointer */
    RtlUnlockHeap(hProcessHeap);
    return hMem;
}

/*
 * @implemented
 */
DWORD
NTAPI
GlobalSize(HGLOBAL hMem)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    PVOID Handle = NULL;
    ULONG Flags = 0;
    SIZE_T dwSize = MAXULONG_PTR;

    /* Lock the heap */
    RtlLockHeap(hProcessHeap);

    /* Check if this is a simple RTL Heap Managed block */
    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
    {
        /* Then we'll query RTL Heap */
        RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
        BASE_TRACE_PTR(Handle, hMem);

        /*
         * Check if RTL Heap didn't give us a handle or said that this heap
         * isn't movable.
         */
        if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
        {
            /* This implies we're not a handle heap, so use the generic call */
            dwSize = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
        }
        else
        {
            /* Otherwise we're a handle heap, so get the internal handle */
            hMem = Handle;
        }
    }

    /* Make sure that this is an entry in our handle database */
    if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
    {
        /* Get the entry */
        HandleEntry = BaseHeapGetEntry(hMem);
        BASE_TRACE_HANDLE(HandleEntry, hMem);

        /* Make sure the handle is valid */
        if (!BaseHeapValidateEntry(HandleEntry))
        {
            /* Fail */
            BASE_TRACE_FAILURE();
            SetLastError(ERROR_INVALID_HANDLE);
        }
        else if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
        {
            /* We've reused this block, but we've saved the size for you */
            dwSize = HandleEntry->OldSize;
        }
        else
        {
            /* Otherwise, query RTL about it */
            dwSize = RtlSizeHeap(hProcessHeap,
                                 HEAP_NO_SERIALIZE,
                                 HandleEntry->Object);
        }
    }

    /* Check if by now, we still haven't gotten any useful size */
    if (dwSize == MAXULONG_PTR)
    {
        /* Fail */
        BASE_TRACE_FAILURE();
        SetLastError(ERROR_INVALID_HANDLE);
        dwSize = 0;
    }

    /* All done! Unlock heap and return the size */
    RtlUnlockHeap(hProcessHeap);
    return dwSize;
}

/*
 * @implemented
 */
VOID
NTAPI
GlobalUnfix(HGLOBAL hMem)
{
    /* If the handle is valid, unlock it */
    if (hMem != INVALID_HANDLE_VALUE) GlobalUnlock(hMem);
}

/*
 * @implemented
 */
BOOL
NTAPI
GlobalUnlock(HGLOBAL hMem)
{
    PBASE_HEAP_HANDLE_ENTRY HandleEntry;
    BOOL RetVal = TRUE;

    /* Check if this was a simple allocated heap entry */
    if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) return RetVal;

    /* Otherwise, lock the heap */
    RtlLockHeap(hProcessHeap);

    /* Get the handle entry */
    HandleEntry = BaseHeapGetEntry(hMem);
    BASE_TRACE_HANDLE(HandleEntry, hMem);

    /* Make sure it's valid */
    if (!BaseHeapValidateEntry(HandleEntry))
    {
        /* It's not, fail */
        BASE_TRACE_FAILURE();
        SetLastError(ERROR_INVALID_HANDLE);
    }
    else
    {
        /* Otherwise, decrement lock count, unless we're already at 0*/
        if (!HandleEntry->LockCount--)
        {
            /* In which case we simply lock it back and fail */
            HandleEntry->LockCount++;
            SetLastError(ERROR_NOT_LOCKED);
            RetVal = FALSE;
        }
        else if (!HandleEntry->LockCount)
        {
            /* Nothing to unlock */
            SetLastError(NO_ERROR);
            RetVal = FALSE;
        }
    }

    /* All done. Unlock the heap and return the pointer */
    RtlUnlockHeap(hProcessHeap);
    return RetVal;
}

/*
 * @implemented
 */
BOOL
NTAPI
GlobalUnWire(HGLOBAL hMem)
{
    /* This is simply an unlock */
    return GlobalUnlock(hMem);
}

/*
 * @implemented
 */
LPVOID
NTAPI
GlobalWire(HGLOBAL hMem)
{
    /* This is just a lock */
    return GlobalLock(hMem);
}

/*
 * @implemented
 */
BOOL
NTAPI
GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
{
    SYSTEM_PERFORMANCE_INFORMATION PerformanceInfo;
    VM_COUNTERS VmCounters;
    QUOTA_LIMITS QuotaLimits;
    ULONGLONG PageFile, PhysicalMemory;

    /* Query performance information */
    NtQuerySystemInformation(SystemPerformanceInformation,
                             &PerformanceInfo,
                             sizeof(PerformanceInfo),
                             NULL);

    /* Calculate memory load */
    lpBuffer->dwMemoryLoad = ((DWORD)(BaseCachedSysInfo.NumberOfPhysicalPages -
                                      PerformanceInfo.AvailablePages) * 100) /
                                      BaseCachedSysInfo.NumberOfPhysicalPages;

    /* Save physical memory */
    PhysicalMemory = BaseCachedSysInfo.NumberOfPhysicalPages *
                     BaseCachedSysInfo.PageSize;
    lpBuffer->ullTotalPhys = PhysicalMemory;

    /* Now save available physical memory */
    PhysicalMemory = PerformanceInfo.AvailablePages *
                     BaseCachedSysInfo.PageSize;
    lpBuffer->ullAvailPhys = PhysicalMemory;

    /* Query VM and Quota Limits */
    NtQueryInformationProcess(NtCurrentProcess(),
                              ProcessQuotaLimits,
                              &QuotaLimits,
                              sizeof(QUOTA_LIMITS),
                              NULL);
    NtQueryInformationProcess(NtCurrentProcess(),
                              ProcessVmCounters,
                              &VmCounters,
                              sizeof(VM_COUNTERS),
                              NULL);

    /* Save the commit limit */
    lpBuffer->ullTotalPageFile = min(QuotaLimits.PagefileLimit,
                                     PerformanceInfo.CommitLimit);

    /* Calculate how many pages are left */
    PageFile = PerformanceInfo.CommitLimit - PerformanceInfo.CommittedPages;

    /* Save the total */
    lpBuffer->ullAvailPageFile = min(PageFile,
                                     QuotaLimits.PagefileLimit -
                                     VmCounters.PagefileUsage);
    lpBuffer->ullAvailPageFile *= BaseCachedSysInfo.PageSize;

    /* Now calculate the total virtual space */
    lpBuffer->ullTotalVirtual = (BaseCachedSysInfo.MaximumUserModeAddress -
                                 BaseCachedSysInfo.MinimumUserModeAddress) + 1;

    /* And finally the avilable virtual space */
    lpBuffer->ullAvailVirtual = lpBuffer->ullTotalVirtual -
                                VmCounters.VirtualSize;
    lpBuffer->ullAvailExtendedVirtual = 0;
    return TRUE;
}

/*
 * @implemented
 */
VOID
NTAPI
GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer)
{
    MEMORYSTATUSEX lpBufferEx;

    /* Call the extended function */
    lpBufferEx.dwLength = sizeof(MEMORYSTATUSEX);
    if (GlobalMemoryStatusEx(&lpBufferEx))
    {
        /* Reset the right size and fill out the information */
        lpBuffer->dwLength = sizeof(MEMORYSTATUS);
        lpBuffer->dwMemoryLoad = lpBufferEx.dwMemoryLoad;
        lpBuffer->dwTotalPhys = lpBufferEx.ullTotalPhys;
        lpBuffer->dwAvailPhys = lpBufferEx.ullAvailPhys;
        lpBuffer->dwTotalPageFile = lpBufferEx.ullTotalPageFile;
        lpBuffer->dwAvailPageFile = lpBufferEx.ullAvailPageFile;
        lpBuffer->dwTotalVirtual = lpBufferEx.ullTotalVirtual;
        lpBuffer->dwAvailVirtual = lpBufferEx.ullAvailVirtual;
    }
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -