vmalloc.c

来自「一本已经绝版的好书」· C语言 代码 · 共 401 行

C
401
字号
/************************************************************
Module name: VMAlloc.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
************************************************************/


#include "..\CmnHdr.H"                  /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h>             // For sprintf
#include "Resource.H"


/////////////////////////////////////////////////////////////


UINT g_uPageSize = 0;

typedef struct {
   BOOL fAllocated;
   BYTE bOtherData[2048 - sizeof(BOOL)];
} SOMEDATA, *PSOMEDATA;

#define MAX_SOMEDATA    (50)
PSOMEDATA g_pSomeData = NULL;

RECT g_rcMemMap;


/////////////////////////////////////////////////////////////


BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus, 
   LPARAM lParam) {
   
   TCHAR szBuf[10];

   // Associate an icon with the dialog box.
   chSETDLGICONS(hwnd, IDI_VMALLOC, IDI_VMALLOC);

   // Initialize the dialog box by disabling all 
   // the nonsetup controls.
   EnableWindow(GetDlgItem(hwnd, IDC_INDEXTEXT), FALSE);
   EnableWindow(GetDlgItem(hwnd, IDC_INDEX), FALSE);
   ScrollBar_SetRange(GetDlgItem(hwnd, IDC_INDEXSCRL), 
      0, MAX_SOMEDATA - 1, FALSE);
   ScrollBar_SetPos(GetDlgItem(hwnd, IDC_INDEXSCRL), 0,TRUE);
   EnableWindow(GetDlgItem(hwnd, IDC_INDEXSCRL), FALSE);
   EnableWindow(GetDlgItem(hwnd, IDC_USE), FALSE);
   EnableWindow(GetDlgItem(hwnd, IDC_CLEAR), FALSE);
   EnableWindow(GetDlgItem(hwnd, IDC_GARBAGECOLLECT), FALSE);

   // Get the coordinates of the memory map display.
   GetWindowRect(GetDlgItem(hwnd, IDC_MEMMAP), &g_rcMemMap);
   MapWindowPoints(NULL, hwnd, (LPPOINT) &g_rcMemMap, 2);

   // Destroy the temporary window that identifies the
   // location of the memory map display.
   DestroyWindow(GetDlgItem(hwnd, IDC_MEMMAP));
   
   // Put the page size in the dialog box just
   // for the user's information.
   _stprintf(szBuf, __TEXT("%d KB"), g_uPageSize / 1024);
   SetDlgItemText(hwnd, IDC_PAGESIZE, szBuf);

   // Initialize the edit control.
   SetDlgItemInt(hwnd, IDC_INDEX, 0, FALSE);
   
   return(TRUE);
}


/////////////////////////////////////////////////////////////


void Dlg_OnDestroy (HWND hwnd) {
   if (g_pSomeData != NULL)
      VirtualFree(g_pSomeData, 0, MEM_RELEASE);
}


/////////////////////////////////////////////////////////////


void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtl, 
   UINT codeNotify) {
   
   UINT uIndex, uIndexLast, uPage, uMaxPages;
   BOOL fTranslated, fOk, fAnyAllocs;
   MEMORY_BASIC_INFORMATION MemoryBasicInfo;

   switch (id) {
      case IDC_RESERVE:
         // Reserve enough address space to hold MAX_SOMEDATA
         // SOMEDATA structures.
         g_pSomeData = (PSOMEDATA) VirtualAlloc(NULL,
            MAX_SOMEDATA * sizeof(SOMEDATA), MEM_RESERVE,
            PAGE_READWRITE);

         // Disable the Reserve button and
         // enable all the other controls.
         EnableWindow(GetDlgItem(hwnd, IDC_RESERVE), FALSE);
         EnableWindow(GetDlgItem(hwnd, IDC_INDEXTEXT), TRUE);
         EnableWindow(GetDlgItem(hwnd, IDC_INDEX), TRUE);
         EnableWindow(GetDlgItem(hwnd, IDC_INDEXSCRL), TRUE);
         EnableWindow(GetDlgItem(hwnd, IDC_USE), TRUE);
         EnableWindow(GetDlgItem(hwnd, IDC_GARBAGECOLLECT),
            TRUE);

         // Force the index edit control to have the focus.
         SetFocus(GetDlgItem(hwnd, IDC_INDEX));
         
         // Invalidate the memory map display.
         InvalidateRect(hwnd, &g_rcMemMap, FALSE);
         break;

      case IDC_INDEX:
         if (codeNotify != EN_CHANGE)
            break;

         uIndex = GetDlgItemInt(hwnd, id, &fTranslated,
            FALSE);
         if ((g_pSomeData == NULL) ||
             (uIndex >= MAX_SOMEDATA)) {
            // If the index is out of range, assume the
            // translation was unsuccessful.
            fTranslated = FALSE;
         }

         if (fTranslated) {
            VirtualQuery(&g_pSomeData[uIndex], 
               &MemoryBasicInfo, sizeof(MemoryBasicInfo));
            fOk = (MemoryBasicInfo.State == MEM_COMMIT);
            if (fOk)
               fOk = g_pSomeData[uIndex].fAllocated;

            EnableWindow(GetDlgItem(hwnd, IDC_USE),  !fOk);
            EnableWindow(GetDlgItem(hwnd, IDC_CLEAR), fOk);
            ScrollBar_SetPos(GetDlgItem(hwnd, IDC_INDEXSCRL),
               uIndex, TRUE);

         } else {
            EnableWindow(GetDlgItem(hwnd, IDC_USE),   FALSE);
            EnableWindow(GetDlgItem(hwnd, IDC_CLEAR), FALSE);
         }
         break;
         

      case IDC_USE:
         uIndex = GetDlgItemInt(hwnd, IDC_INDEX, &fTranslated, 
            FALSE);

         if (uIndex >= MAX_SOMEDATA) {
            // If the index is out of range, assume the
            // translation was unsuccessful.
            fTranslated = FALSE;
         }

         if (fTranslated) {
            VirtualAlloc(&g_pSomeData[uIndex], 
               sizeof(SOMEDATA), MEM_COMMIT, PAGE_READWRITE);

            // When pages are committed, Windows NT ensures
            // that they are zeroed.
            g_pSomeData[uIndex].fAllocated = TRUE;

            EnableWindow(GetDlgItem(hwnd, IDC_USE),   FALSE);
            EnableWindow(GetDlgItem(hwnd, IDC_CLEAR), TRUE);

            // Force the Clear button control to 
            // have the focus.
            SetFocus(GetDlgItem(hwnd, IDC_CLEAR));
         
            // Invalidate the memory map display.
            InvalidateRect(hwnd, &g_rcMemMap, FALSE);
         }
         break;

      case IDC_CLEAR:
         uIndex = GetDlgItemInt(hwnd, IDC_INDEX, &fTranslated, 
            FALSE);

         if (uIndex >= MAX_SOMEDATA) {
            // If the index is out of range, assume the
            // translation was unsuccessful.
            fTranslated = FALSE;
         }

         if (fTranslated) {
            g_pSomeData[uIndex].fAllocated = FALSE;
            EnableWindow(GetDlgItem(hwnd, IDC_USE),   TRUE);
            EnableWindow(GetDlgItem(hwnd, IDC_CLEAR), FALSE);

            // Force the Use button control to have the focus.
            SetFocus(GetDlgItem(hwnd, IDC_USE));
         }
         break;

      case IDC_GARBAGECOLLECT:
         uMaxPages = MAX_SOMEDATA * sizeof(SOMEDATA) /
            g_uPageSize;

         for (uPage = 0; uPage < uMaxPages; uPage++) {
            fAnyAllocs = FALSE;

            uIndex = uPage * g_uPageSize / sizeof(SOMEDATA);

            uIndexLast = uIndex + g_uPageSize / 
               sizeof(SOMEDATA);

            for (; uIndex < uIndexLast; uIndex++) {
               VirtualQuery(&g_pSomeData[uIndex], 
                  &MemoryBasicInfo, sizeof(MemoryBasicInfo));

               if ((MemoryBasicInfo.State == MEM_COMMIT) &&
                  g_pSomeData[uIndex].fAllocated) {

                  fAnyAllocs = TRUE;
                  break;
               }
            }

            if (!fAnyAllocs) {
               // No allocated structures exist in the page.
               // We can safely decommit it.
               VirtualFree(&g_pSomeData[uIndexLast - 1],
                  sizeof(SOMEDATA), MEM_DECOMMIT);
            }
         }

         // Invalidate the memory map display.
         InvalidateRect(hwnd, &g_rcMemMap, FALSE);
         break;

      case IDCANCEL:
         EndDialog(hwnd, id);
         break;
   }
}


/////////////////////////////////////////////////////////////


void Dlg_OnHScroll (HWND hwnd, HWND hwndCtl, 
   UINT code, int pos) {
   
   INT nScrlPos;
   if (hwndCtl != GetDlgItem(hwnd, IDC_INDEXSCRL))
      return;

   nScrlPos = ScrollBar_GetPos(hwndCtl);
   switch (code) {
      case SB_LINELEFT:
         nScrlPos--;
         break;

      case SB_LINERIGHT:
         nScrlPos++;
         break;

      case SB_PAGELEFT:
         nScrlPos -= g_uPageSize / sizeof(SOMEDATA);
         break;

      case SB_PAGERIGHT:
         nScrlPos += g_uPageSize / sizeof(SOMEDATA);
         break;

      case SB_THUMBTRACK:
         nScrlPos = pos;
         break;

      case SB_LEFT:
         nScrlPos = 0;
         break;

      case SB_RIGHT:
         nScrlPos = MAX_SOMEDATA - 1;
         break;
   }

   if (nScrlPos < 0)
      nScrlPos = 0;

   if (nScrlPos >= MAX_SOMEDATA)
      nScrlPos = MAX_SOMEDATA - 1;

   ScrollBar_SetPos(hwndCtl, nScrlPos, TRUE);
   SetDlgItemInt(hwnd, IDC_INDEX, nScrlPos, TRUE);
}


/////////////////////////////////////////////////////////////


void Dlg_OnPaint (HWND hwnd) {
   UINT uPage, uIndex, uIndexLast, uMemMapWidth;
   UINT uMaxPages = MAX_SOMEDATA * sizeof(SOMEDATA) / 
      g_uPageSize;

   MEMORY_BASIC_INFORMATION MemoryBasicInfo;
   PAINTSTRUCT ps;

   BeginPaint(hwnd, &ps);

   if (g_pSomeData == NULL) {
      // The memory has yet to be reserved.
      Rectangle(ps.hdc, g_rcMemMap.left, g_rcMemMap.top,
         g_rcMemMap.right, g_rcMemMap.bottom);
   }

   // Walk the virtual address space, adding 
   // entries to the list box.
   uPage = 0;
   while ((g_pSomeData != NULL) && uPage < uMaxPages) {

      uIndex = uPage * g_uPageSize / sizeof(SOMEDATA);

      uIndexLast = uIndex + g_uPageSize / sizeof(SOMEDATA);

      for (; uIndex < uIndexLast; uIndex++) {

         VirtualQuery(&g_pSomeData[uIndex], &MemoryBasicInfo,
            sizeof(MemoryBasicInfo));

         switch (MemoryBasicInfo.State) {
            case MEM_FREE:
               SelectObject(ps.hdc, 
                  GetStockObject(WHITE_BRUSH));
               break;

            case MEM_RESERVE:
               SelectObject(ps.hdc, 
                  GetStockObject(GRAY_BRUSH));
               break;

            case MEM_COMMIT:
               SelectObject(ps.hdc, 
                  GetStockObject(BLACK_BRUSH));
               break;
         }

         uMemMapWidth = g_rcMemMap.right - g_rcMemMap.left;
         Rectangle(ps.hdc,
            g_rcMemMap.left + 
               uMemMapWidth / uMaxPages * uPage,
            g_rcMemMap.top,
            g_rcMemMap.left + 
               uMemMapWidth / uMaxPages * (uPage + 1),
            g_rcMemMap.bottom);

      }

      uPage++;
   }

   EndPaint(hwnd, &ps);
}


/////////////////////////////////////////////////////////////


BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, 
   WPARAM wParam, LPARAM lParam) {
   
   switch (uMsg) {
      chHANDLE_DLGMSG(hwnd, WM_INITDIALOG,  Dlg_OnInitDialog);
      chHANDLE_DLGMSG(hwnd, WM_COMMAND,  Dlg_OnCommand);
      chHANDLE_DLGMSG(hwnd, WM_HSCROLL,  Dlg_OnHScroll);
      chHANDLE_DLGMSG(hwnd, WM_PAINT,    Dlg_OnPaint);
      chHANDLE_DLGMSG(hwnd, WM_DESTROY,  Dlg_OnDestroy);
   }
   return(FALSE);
}


/////////////////////////////////////////////////////////////


int WINAPI _tWinMain (HINSTANCE hinstExe,
   HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {

   SYSTEM_INFO SystemInfo;

   chWARNIFUNICODEUNDERWIN95();

   // Get the page size used on this CPU.
   GetSystemInfo(&SystemInfo);
   g_uPageSize = SystemInfo.dwPageSize;

   DialogBox(hinstExe, MAKEINTRESOURCE(IDD_VMALLOC), 
      NULL, Dlg_Proc);
   return(0);
}


/////////////////////// End Of File ///////////////////////

⌨️ 快捷键说明

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