home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap02 / malloc2 / malloc2.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  12KB  |  576 lines

  1. /*
  2.  * MALLOC2.CPP
  3.  * C++ Malloc Demonstration Chapter 2
  4.  *
  5.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  6.  *
  7.  * Kraig Brockschmidt, Microsoft
  8.  * Internet  :  kraigb@microsoft.com
  9.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  10.  */
  11.  
  12.  
  13. #include "malloc2.h"
  14.  
  15.  
  16. /*
  17.  * WinMain
  18.  *
  19.  * Purpose:
  20.  *  Main entry point of application.
  21.  */
  22.  
  23. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev
  24.     , LPSTR pszCmdLine, int nCmdShow)
  25.     {
  26.     MSG         msg;
  27.     PAPP        pApp;
  28.     DWORD       dwVer;
  29.     HRESULT     hr;
  30.  
  31.     SETMESSAGEQUEUE;
  32.  
  33.     //Make sure COM is the right version
  34.     dwVer=CoBuildVersion();
  35.  
  36.     if (rmm!=HIWORD(dwVer))
  37.         return 0;
  38.  
  39.     //Initialize OLE
  40.     hr=CoInitialize(NULL);
  41.  
  42.     if (FAILED(hr))
  43.         return 0;
  44.  
  45.     pApp=new CApp(hInst, hInstPrev, nCmdShow);
  46.  
  47.     if (NULL!=pApp)
  48.         {
  49.         if (pApp->Init())
  50.             {
  51.             while (GetMessage(&msg, NULL, 0,0 ))
  52.                 {
  53.                 TranslateMessage(&msg);
  54.                 DispatchMessage(&msg);
  55.                 }
  56.             }
  57.  
  58.         delete pApp;
  59.         }
  60.  
  61.     //Only call this if CoInitialize worked
  62.     CoUninitialize();
  63.     return 0;
  64.     }
  65.  
  66.  
  67.  
  68.  
  69.  
  70. /*
  71.  * MallocWndProc
  72.  *
  73.  * Purpose:
  74.  *  Standard window class procedure.
  75.  */
  76.  
  77. LRESULT APIENTRY MallocWndProc(HWND hWnd, UINT iMsg
  78.     , WPARAM wParam, LPARAM lParam)
  79.     {
  80.     PAPP        pApp;
  81.     ULONG       cb;
  82.     UINT        i;
  83.     BOOL        fResult;
  84.  
  85.     pApp=(PAPP)GetWindowLong(hWnd, MALLOCWL_STRUCTURE);
  86.  
  87.     switch (iMsg)
  88.         {
  89.         case WM_NCCREATE:
  90.             pApp=(PAPP)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  91.             SetWindowLong(hWnd, MALLOCWL_STRUCTURE, (LONG)pApp);
  92.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  93.  
  94.         case WM_DESTROY:
  95.             PostQuitMessage(0);
  96.             break;
  97.  
  98.         case WM_COMMAND:
  99.             switch (LOWORD(wParam))
  100.                 {
  101.                 case IDM_COGETMALLOC:
  102.                     pApp->GetAllocator();
  103.                     break;
  104.  
  105.  
  106.                 case IDM_RELEASE:
  107.                     if (!pApp->HaveAllocator())
  108.                         break;
  109.  
  110.                     pApp->FreeAllocations(TRUE);
  111.                     pApp->Message(TEXT("Release complete"));
  112.                     break;
  113.  
  114.  
  115.                 case IDM_ALLOC:
  116.                     if (!pApp->HaveAllocator())
  117.                         break;
  118.  
  119.                     fResult=pApp->DoAllocations(FALSE);
  120.  
  121.                     pApp->Message(fResult ? TEXT("Alloc succeeded")
  122.                         : TEXT("Alloc failed"));
  123.  
  124.                     break;
  125.  
  126.  
  127.                 case IDM_FREE:
  128.                     if (!pApp->HaveAllocations())
  129.                         break;
  130.  
  131.                     pApp->FreeAllocations(FALSE);
  132.                     pApp->Message(TEXT("Free complete"));
  133.                     break;
  134.  
  135.  
  136.                 case IDM_REALLOC:
  137.                     if (!pApp->HaveAllocator())
  138.                         break;
  139.  
  140.                     fResult=pApp->DoAllocations(TRUE);
  141.  
  142.                     pApp->Message(fResult ? TEXT("Realloc succeeded")
  143.                         : TEXT("Realloc failed"));
  144.  
  145.                     break;
  146.  
  147.  
  148.                 case IDM_GETSIZE:
  149.                     if (!pApp->HaveAllocations())
  150.                         break;
  151.  
  152.                     fResult=TRUE;
  153.  
  154.                     for (i=0; i < CALLOCS; i++)
  155.                         {
  156.                         cb=pApp->m_pIMalloc->GetSize(pApp->m_rgpv[i]);
  157.  
  158.                         /*
  159.                          * We test that the size is *at least*
  160.                          * what we wanted.
  161.                          */
  162.                         fResult &= (pApp->m_rgcb[i] <= cb);
  163.                         }
  164.  
  165.                     pApp->Message(fResult ? TEXT("Sizes matched")
  166.                         : TEXT("Sizes mismatch"));
  167.  
  168.                     break;
  169.  
  170.  
  171.                 case IDM_DIDALLOC:
  172.                     if (!pApp->HaveAllocations())
  173.                         break;
  174.  
  175.                     /*
  176.                      * DidAlloc may return -1 if it does not know
  177.                      * whether or not it actually allocated
  178.                      * something.  In that case we just blindly
  179.                      * & in a -1 with no affect.
  180.                      */
  181.  
  182.                     fResult=(BOOL)-1;
  183.  
  184.                     for (i=0; i < CALLOCS; i++)
  185.                         {
  186.                         fResult &= pApp->m_pIMalloc
  187.                             ->DidAlloc(pApp->m_rgpv[i]);
  188.                         }
  189.  
  190.                     if (0==fResult)
  191.                         pApp->Message(TEXT("DidAlloc is FALSE"));
  192.  
  193.                     if (1==fResult)
  194.                         pApp->Message(TEXT("DidAlloc is TRUE"));
  195.  
  196.                     if (-1==fResult)
  197.                         pApp->Message(TEXT("DidAlloc is unknown"));
  198.  
  199.                     break;
  200.  
  201.  
  202.                 case IDM_HEAPMINIMIZE:
  203.                     if (!pApp->HaveAllocator())
  204.                         break;
  205.  
  206.                     pApp->m_pIMalloc->HeapMinimize();
  207.                     pApp->Message(TEXT("HeapMinimize finished"));
  208.                     break;
  209.  
  210.  
  211.                 case IDM_EXIT:
  212.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  213.                     break;
  214.                 }
  215.             break;
  216.  
  217.         default:
  218.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  219.         }
  220.  
  221.     return 0L;
  222.     }
  223.  
  224.  
  225.  
  226.  
  227.  
  228. /*
  229.  * CApp::CApp
  230.  * CApp::~CApp
  231.  *
  232.  * Constructor Parameters: (from WinMain)
  233.  *  hInst           HINSTANCE of the application.
  234.  *  hInstPrev       HINSTANCE of a previous instance.
  235.  *  nCmdShow        UINT specifying how to show the app window.
  236.  */
  237.  
  238. CApp::CApp(HINSTANCE hInst, HINSTANCE hInstPrev
  239.     , UINT nCmdShow)
  240.     {
  241.     UINT        i;
  242.     ULONG       cb;
  243.  
  244.     m_hInst       =hInst;
  245.     m_hInstPrev   =hInstPrev;
  246.     m_nCmdShow    =nCmdShow;
  247.  
  248.     m_hWnd        =NULL;
  249.     m_pIMalloc    =NULL;
  250.     m_fAllocated  =FALSE;
  251.  
  252.     //100 is arbitrary.  IMalloc can handle larger.
  253.     cb=100;
  254.  
  255.     for (i=0; i < CALLOCS; i++)
  256.         {
  257.         m_rgcb[i]=cb;
  258.         m_rgpv[i]=NULL;
  259.  
  260.         cb*=2;
  261.         }
  262.  
  263.     return;
  264.     }
  265.  
  266.  
  267.  
  268. CApp::~CApp(void)
  269.     {
  270.     FreeAllocations(TRUE);
  271.     return;
  272.     }
  273.  
  274.  
  275.  
  276.  
  277.  
  278. /*
  279.  * CApp::Init
  280.  *
  281.  * Purpose:
  282.  *  Initializes an CApp object by registering window classes,
  283.  *  creating the main window, and doing anything else prone to
  284.  *  failure.  If this function fails the caller should insure
  285.  *  that the destructor is called.
  286.  *
  287.  * Parameters:
  288.  *  None
  289.  *
  290.  * Return Value:
  291.  *  BOOL            TRUE if successful, FALSE otherwise.
  292.  */
  293.  
  294. BOOL CApp::Init(void)
  295.     {
  296.     WNDCLASS    wc;
  297.  
  298.     if (!m_hInstPrev)
  299.         {
  300.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  301.         wc.lpfnWndProc    = MallocWndProc;
  302.         wc.cbClsExtra     = 0;
  303.         wc.cbWndExtra     = CBWNDEXTRA;
  304.         wc.hInstance      = m_hInst;
  305.         wc.hIcon          = LoadIcon(m_hInst, TEXT("Icon"));
  306.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  307.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  308.         wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU);
  309.         wc.lpszClassName  = TEXT("MALLOC2");
  310.  
  311.         if (!RegisterClass(&wc))
  312.             return FALSE;
  313.         }
  314.  
  315.     m_hWnd=CreateWindow(TEXT("MALLOC2"), TEXT("C++ Malloc Demo")
  316.         , WS_OVERLAPPEDWINDOW, 35, 35, 350, 250, NULL, NULL
  317.         , m_hInst, this);
  318.  
  319.     if (NULL==m_hWnd)
  320.         return FALSE;
  321.  
  322.     ShowWindow(m_hWnd, m_nCmdShow);
  323.     UpdateWindow(m_hWnd);
  324.  
  325.     return TRUE;
  326.     }
  327.  
  328.  
  329.  
  330.  
  331. /*
  332.  * CApp::GetAllocator
  333.  *
  334.  * Purpose:
  335.  *  Retrieves the current allocator.
  336.  *
  337.  * Parameters:
  338.  *  None
  339.  *
  340.  * Return Value:
  341.  *  None
  342.  */
  343.  
  344. void CApp::GetAllocator(void)
  345.     {
  346.     HRESULT     hr;
  347.     TCHAR       szTemp[80];
  348.  
  349.     //This also releases m_pIMalloc
  350.     FreeAllocations(TRUE);
  351.  
  352.     hr=CoGetMalloc(MEMCTX_TASK, &m_pIMalloc);
  353.  
  354.     wsprintf(szTemp, TEXT("CoGetMalloc %s")
  355.         , SUCCEEDED(hr) ? TEXT("succeeded") : TEXT("failed"));
  356.  
  357.     Message(szTemp);
  358.     return;
  359.     }
  360.  
  361.  
  362.  
  363. /*
  364.  * CApp::HaveAllocator
  365.  *
  366.  * Purpose:
  367.  *  Checks if there's a valid allocator and displays a
  368.  *  message if not.
  369.  *
  370.  * Parameters:
  371.  *  None
  372.  *
  373.  * Return Value:
  374.  *  BOOL            TRUE if there is an allocator, FALSE otherwise.
  375.  */
  376.  
  377. BOOL CApp::HaveAllocator(void)
  378.     {
  379.     if (NULL==m_pIMalloc)
  380.         {
  381.         Message(TEXT("Create the allocator first"));
  382.         return FALSE;
  383.         }
  384.  
  385.     return TRUE;
  386.     }
  387.  
  388.  
  389.  
  390.  
  391. /*
  392.  * CApp::DoAllocations
  393.  *
  394.  * Purpose:
  395.  *  Centralized place to clean up allocations made on
  396.  *  the current IMalloc.
  397.  *
  398.  * Parameters:
  399.  *  fRelease        BOOL indicating if we're to
  400.  *                  IMalloc::Release as well.
  401.  *
  402.  * Return Value:
  403.  *  BOOL            TRUE if all allocations succeeded.
  404.  */
  405.  
  406. BOOL CApp::DoAllocations(BOOL fRealloc)
  407.     {
  408.     UINT        i;
  409.     ULONG       iByte;
  410.     BOOL        fResult=TRUE;
  411.     ULONG       cb;
  412.     LPVOID      pv;
  413.  
  414.     if (!fRealloc)
  415.         FreeAllocations(FALSE);
  416.  
  417.     for (i=0; i < CALLOCS; i++)
  418.         {
  419.         //cb is set in the code below for later initialization
  420.         if (fRealloc)
  421.             {
  422.             m_rgcb[i]+=128;
  423.             cb=m_rgcb[i];
  424.  
  425.             //Old memory is not freed if Realloc fails
  426.             pv=m_pIMalloc->Realloc(m_rgpv[i], cb);
  427.             }
  428.         else
  429.             {
  430.             cb=m_rgcb[i];
  431.             pv=m_pIMalloc->Alloc(cb);
  432.             }
  433.  
  434.         m_rgpv[i]=pv;
  435.  
  436.         //Fill the memory with letters.
  437.         if (NULL!=pv)
  438.             {
  439.             LPBYTE  pb=(LPBYTE)pv;
  440.  
  441.             for (iByte=0; iByte < cb; iByte++)
  442.                 *pb++=('a'+i);
  443.             }
  444.  
  445.         fResult &= (NULL!=pv);
  446.         }
  447.  
  448.     m_fAllocated=fResult;
  449.  
  450.     //Clean up whatever we might have allocated
  451.     if (!fResult)
  452.         FreeAllocations(FALSE);
  453.  
  454.     return fResult;
  455.     }
  456.  
  457.  
  458.  
  459.  
  460. /*
  461.  * CApp::HaveAllocations
  462.  *
  463.  * Purpose:
  464.  *  Checks if we have allocated memory from the current allocator,
  465.  *  displaying a message if not.
  466.  *
  467.  * Parameters:
  468.  *  None
  469.  *
  470.  * Return Value:
  471.  *  BOOL            TRUE if there are allocations, FALSE otherwise.
  472.  */
  473.  
  474. BOOL CApp::HaveAllocations(void)
  475.     {
  476.     if (!HaveAllocator())
  477.         return FALSE;
  478.  
  479.     if (!m_fAllocated)
  480.         {
  481.         Message(TEXT("Choose Alloc first"));
  482.         return FALSE;
  483.         }
  484.  
  485.     return TRUE;
  486.     }
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493. /*
  494.  * CApp::FreeAllocations
  495.  *
  496.  * Purpose:
  497.  *  Centralized place to clean up allocations made on
  498.  *  the current IMalloc.
  499.  *
  500.  * Parameters:
  501.  *  fRelease        BOOL indicating if we're to
  502.  *                  IMalloc::Release as well.
  503.  *
  504.  * Return Value:
  505.  *  None
  506.  */
  507.  
  508. void CApp::FreeAllocations(BOOL fRelease)
  509.     {
  510.     UINT    i;
  511.  
  512.     if (NULL==m_pIMalloc)
  513.         return;
  514.  
  515.     if (m_fAllocated)
  516.         {
  517.         for (i=0; i < CALLOCS; i++)
  518.             {
  519.             if (NULL!=m_rgpv[i])
  520.                 m_pIMalloc->Free(m_rgpv[i]);
  521.  
  522.             m_rgpv[i]=NULL;
  523.             }
  524.  
  525.         m_fAllocated=FALSE;
  526.         }
  527.  
  528.     if (fRelease)
  529.         {
  530.         m_pIMalloc->Release();
  531.         m_pIMalloc=NULL;
  532.         }
  533.  
  534.     return;
  535.     }
  536.  
  537.  
  538.  
  539.  
  540.  
  541. /*
  542.  * CApp::Message
  543.  *
  544.  * Purpose:
  545.  *  Displays a message in the client area of the window.  This is
  546.  *  just to centralize the call to simpify other code.
  547.  *
  548.  * Parameters:
  549.  *  psz             LPTSTR to the string to display.
  550.  *
  551.  * Return Value:
  552.  *  None
  553.  */
  554.  
  555. void CApp::Message(LPTSTR psz)
  556.     {
  557.     HDC     hDC;
  558.     RECT    rc;
  559.  
  560.     hDC=GetDC(m_hWnd);
  561.     GetClientRect(m_hWnd, &rc);
  562.  
  563.     SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  564.     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  565.  
  566.     /*
  567.      * We'll just be sloppy and clear the whole window as
  568.      * well as write the string with one ExtTextOut call.
  569.      * No word wrapping here...
  570.      */
  571.  
  572.     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, psz, lstrlen(psz), NULL);
  573.     ReleaseDC(m_hWnd, hDC);
  574.     return;
  575.     }
  576.