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 / malloc1 / malloc1.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  14KB  |  594 lines

  1. /*
  2.  * MALLOC1.C
  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 "malloc1.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=App_Create(hInst, hInstPrev, nCmdShow);
  46.  
  47.     if (NULL!=pApp)
  48.         {
  49.         if (App_Init(pApp))
  50.             {
  51.             while (GetMessage(&msg, NULL, 0,0 ))
  52.                 {
  53.                 TranslateMessage(&msg);
  54.                 DispatchMessage(&msg);
  55.                 }
  56.             }
  57.  
  58.         App_Destroy(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.                     App_GetAllocator(pApp);
  103.                     break;
  104.  
  105.  
  106.                 case IDM_RELEASE:
  107.                     if (!App_HaveAllocator(pApp))
  108.                         break;
  109.  
  110.                     App_FreeAllocations(pApp, TRUE);
  111.                     App_Message(pApp, TEXT("Release complete"));
  112.                     break;
  113.  
  114.  
  115.                 case IDM_ALLOC:
  116.                     if (!App_HaveAllocator(pApp))
  117.                         break;
  118.  
  119.                     fResult=App_DoAllocations(pApp, FALSE);
  120.  
  121.                     App_Message(pApp, fResult
  122.                         ? TEXT("Alloc succeeded")
  123.                         : TEXT("Alloc failed"));
  124.  
  125.                     break;
  126.  
  127.  
  128.                 case IDM_FREE:
  129.                     if (!App_HaveAllocations(pApp))
  130.                         break;
  131.  
  132.                     App_FreeAllocations(pApp, FALSE);
  133.                     App_Message(pApp, TEXT("Free complete"));
  134.                     break;
  135.  
  136.  
  137.                 case IDM_REALLOC:
  138.                     if (!App_HaveAllocator(pApp))
  139.                         break;
  140.  
  141.                     fResult=App_DoAllocations(pApp, TRUE);
  142.  
  143.                     App_Message(pApp, fResult
  144.                         ? TEXT("Realloc succeeded")
  145.                         : TEXT("Realloc failed"));
  146.  
  147.                     break;
  148.  
  149.  
  150.                 case IDM_GETSIZE:
  151.                     if (!App_HaveAllocations(pApp))
  152.                         break;
  153.  
  154.                     fResult=TRUE;
  155.  
  156.                     for (i=0; i < CALLOCS; i++)
  157.                         {
  158.                         cb=pApp->m_pIMalloc->lpVtbl->GetSize
  159.                             (pApp->m_pIMalloc, pApp->m_rgpv[i]);
  160.  
  161.                         /*
  162.                          * We test that the size is *at least*
  163.                          * what we wanted.
  164.                          */
  165.                         fResult &= (pApp->m_rgcb[i] <= cb);
  166.                         }
  167.  
  168.                     App_Message(pApp, fResult
  169.                         ? TEXT("Sizes matched")
  170.                         : TEXT("Sizes mismatch"));
  171.  
  172.                     break;
  173.  
  174.  
  175.                 case IDM_DIDALLOC:
  176.                     if (!App_HaveAllocations(pApp))
  177.                         break;
  178.  
  179.                     /*
  180.                      * DidAlloc may return -1 if it does not know
  181.                      * whether or not it actually allocated
  182.                      * something.  In that case we just blindly
  183.                      * & in a -1 with no affect.
  184.                      */
  185.  
  186.                     fResult=(BOOL)-1;
  187.  
  188.                     for (i=0; i < CALLOCS; i++)
  189.                         {
  190.                         fResult &= pApp->m_pIMalloc->lpVtbl->DidAlloc
  191.                             (pApp->m_pIMalloc, pApp->m_rgpv[i]);
  192.                         }
  193.  
  194.                     if (0==fResult)
  195.                         App_Message(pApp, TEXT("DidAlloc is FALSE"));
  196.  
  197.                     if (1==fResult)
  198.                         App_Message(pApp, TEXT("DidAlloc is TRUE"));
  199.  
  200.                     if (-1==fResult)
  201.                         App_Message(pApp, TEXT("DidAlloc is unknown"));
  202.  
  203.                     break;
  204.  
  205.  
  206.                 case IDM_HEAPMINIMIZE:
  207.                     if (!App_HaveAllocator(pApp))
  208.                         break;
  209.  
  210.                     pApp->m_pIMalloc->lpVtbl->HeapMinimize
  211.                         (pApp->m_pIMalloc);
  212.                     App_Message(pApp, TEXT("HeapMinimize finished"));
  213.                     break;
  214.  
  215.  
  216.                 case IDM_EXIT:
  217.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  218.                     break;
  219.                 }
  220.             break;
  221.  
  222.         default:
  223.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  224.         }
  225.  
  226.     return 0L;
  227.     }
  228.  
  229.  
  230.  
  231.  
  232.  
  233. /*
  234.  * App_Create
  235.  * App_Destroy
  236.  *
  237.  * Constructor Parameters: (from WinMain)
  238.  *  hInst           HINSTANCE of the application.
  239.  *  hInstPrev       HINSTANCE of a previous instance.
  240.  *  nCmdShow        UINT specifying how to show the app window.
  241.  */
  242.  
  243. PAPP App_Create(HINSTANCE hInst, HINSTANCE hInstPrev, UINT nCmdShow)
  244.     {
  245.     UINT        i;
  246.     ULONG       cb;
  247.     PAPP        pApp;
  248.  
  249.     pApp=(PAPP)malloc(sizeof(APP));
  250.  
  251.     if (NULL==pApp)
  252.         return NULL;
  253.  
  254.     pApp->m_hInst       =hInst;
  255.     pApp->m_hInstPrev   =hInstPrev;
  256.     pApp->m_nCmdShow    =nCmdShow;
  257.  
  258.     pApp->m_hWnd        =NULL;
  259.     pApp->m_pIMalloc    =NULL;
  260.     pApp->m_fAllocated  =FALSE;
  261.  
  262.     //100 is arbitrary.  IMalloc can handle larger.
  263.     cb=100;
  264.  
  265.     for (i=0; i < CALLOCS; i++)
  266.         {
  267.         pApp->m_rgcb[i]=cb;
  268.         pApp->m_rgpv[i]=NULL;
  269.  
  270.         cb*=2;
  271.         }
  272.  
  273.     return pApp;
  274.     }
  275.  
  276.  
  277.  
  278. void App_Destroy(PAPP pApp)
  279.     {
  280.     App_FreeAllocations(pApp, TRUE);
  281.     free(pApp);
  282.     return;
  283.     }
  284.  
  285.  
  286.  
  287.  
  288.  
  289. /*
  290.  * App_Init
  291.  *
  292.  * Purpose:
  293.  *  Initializes an CApp object by registering window classes,
  294.  *  creating the main window, and doing anything else prone to
  295.  *  failure.  If this function fails the caller should insure
  296.  *  that the destructor is called.
  297.  *
  298.  * Parameters:
  299.  *  pApp            PAPP identifying the object.
  300.  *
  301.  * Return Value:
  302.  *  BOOL            TRUE if successful, FALSE otherwise.
  303.  */
  304.  
  305. BOOL App_Init(PAPP pApp)
  306.     {
  307.     WNDCLASS    wc;
  308.  
  309.     if (!pApp->m_hInstPrev)
  310.         {
  311.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  312.         wc.lpfnWndProc    = MallocWndProc;
  313.         wc.cbClsExtra     = 0;
  314.         wc.cbWndExtra     = CBWNDEXTRA;
  315.         wc.hInstance      = pApp->m_hInst;
  316.         wc.hIcon          = LoadIcon(pApp->m_hInst, TEXT("Icon"));
  317.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  318.         wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  319.         wc.lpszMenuName   = MAKEINTRESOURCE(IDR_MENU);
  320.         wc.lpszClassName  = TEXT("MALLOC");
  321.  
  322.         if (!RegisterClass(&wc))
  323.             return FALSE;
  324.         }
  325.  
  326.     pApp->m_hWnd=CreateWindow(TEXT("MALLOC")
  327.         , TEXT("C Malloc Demo"), WS_OVERLAPPEDWINDOW, 35, 35
  328.         , 350, 250, NULL, NULL, pApp->m_hInst, pApp);
  329.  
  330.     if (NULL==pApp->m_hWnd)
  331.         return FALSE;
  332.  
  333.     ShowWindow(pApp->m_hWnd, pApp->m_nCmdShow);
  334.     UpdateWindow(pApp->m_hWnd);
  335.  
  336.     return TRUE;
  337.     }
  338.  
  339.  
  340.  
  341.  
  342. /*
  343.  * App_GetAllocator
  344.  *
  345.  * Purpose:
  346.  *  Retrieves the current allocator.
  347.  *
  348.  * Parameters:
  349.  *  pApp            PAPP identifying the object.
  350.  *
  351.  * Return Value:
  352.  *  None
  353.  */
  354.  
  355. void App_GetAllocator(PAPP pApp)
  356.     {
  357.     HRESULT     hr;
  358.     TCHAR       szTemp[80];
  359.  
  360.     //This also releases pApp->m_pIMalloc
  361.     App_FreeAllocations(pApp, TRUE);
  362.  
  363.     hr=CoGetMalloc(MEMCTX_TASK, &pApp->m_pIMalloc);
  364.  
  365.     wsprintf(szTemp, TEXT("CoGetMalloc %s")
  366.         , SUCCEEDED(hr) ? TEXT("succeeded") : TEXT("failed"));
  367.  
  368.     App_Message(pApp, szTemp);
  369.     return;
  370.     }
  371.  
  372.  
  373.  
  374. /*
  375.  * App_HaveAllocator
  376.  *
  377.  * Purpose:
  378.  *  Checks if there's a valid allocator and displays a
  379.  *  message if not.
  380.  *
  381.  * Parameters:
  382.  *  pApp            PAPP identifying the object.
  383.  *
  384.  * Return Value:
  385.  *  BOOL            TRUE if there is an allocator, FALSE otherwise.
  386.  */
  387.  
  388. BOOL App_HaveAllocator(PAPP pApp)
  389.     {
  390.     if (NULL==pApp->m_pIMalloc)
  391.         {
  392.         App_Message(pApp, TEXT("Create the allocator first"));
  393.         return FALSE;
  394.         }
  395.  
  396.     return TRUE;
  397.     }
  398.  
  399.  
  400.  
  401.  
  402. /*
  403.  * App_DoAllocations
  404.  *
  405.  * Purpose:
  406.  *  Centralized place to clean up allocations made on
  407.  *  the current IMalloc.
  408.  *
  409.  * Parameters:
  410.  *  pApp            PAPP identifying the object.
  411.  *  fRelease        BOOL indicating if we're to
  412.  *                  IMalloc::Release as well.
  413.  *
  414.  * Return Value:
  415.  *  BOOL            TRUE if all allocations succeeded.
  416.  */
  417.  
  418. BOOL App_DoAllocations(PAPP pApp, BOOL fRealloc)
  419.     {
  420.     UINT        i;
  421.     ULONG       iByte;
  422.     BOOL        fResult=TRUE;
  423.     ULONG       cb;
  424.     LPVOID      pv;
  425.  
  426.     if (!fRealloc)
  427.         App_FreeAllocations(pApp, FALSE);
  428.  
  429.     for (i=0; i < CALLOCS; i++)
  430.         {
  431.         //cb is set in the code below for later initialization
  432.         if (fRealloc)
  433.             {
  434.             pApp->m_rgcb[i]+=128;
  435.             cb=pApp->m_rgcb[i];
  436.  
  437.             //Old memory is not freed if Realloc fails
  438.             pv=pApp->m_pIMalloc->lpVtbl->Realloc(pApp->m_pIMalloc
  439.                 , pApp->m_rgpv[i], cb);
  440.             }
  441.         else
  442.             {
  443.             cb=pApp->m_rgcb[i];
  444.             pv=pApp->m_pIMalloc->lpVtbl->Alloc(pApp->m_pIMalloc, cb);
  445.             }
  446.  
  447.         pApp->m_rgpv[i]=pv;
  448.  
  449.         //Fill the memory with letters.
  450.         if (NULL!=pv)
  451.             {
  452.             LPBYTE  pb=(LPBYTE)pv;
  453.  
  454.             for (iByte=0; iByte < cb; iByte++)
  455.                 *pb++=('a'+i);
  456.             }
  457.  
  458.         fResult &= (NULL!=pv);
  459.         }
  460.  
  461.     pApp->m_fAllocated=fResult;
  462.  
  463.     //Clean up whatever we might have allocated
  464.     if (!fResult)
  465.         App_FreeAllocations(pApp, FALSE);
  466.  
  467.     return fResult;
  468.     }
  469.  
  470.  
  471.  
  472.  
  473. /*
  474.  * App_HaveAllocations
  475.  *
  476.  * Purpose:
  477.  *  Checks if we have allocated memory from the current allocator,
  478.  *  displaying a message if not.
  479.  *
  480.  * Parameters:
  481.  *  pApp            PAPP identifying the object.
  482.  *
  483.  * Return Value:
  484.  *  BOOL            TRUE if there are allocations, FALSE otherwise.
  485.  */
  486.  
  487. BOOL App_HaveAllocations(PAPP pApp)
  488.     {
  489.     if (!App_HaveAllocator(pApp))
  490.         return FALSE;
  491.  
  492.     if (!pApp->m_fAllocated)
  493.         {
  494.         App_Message(pApp, TEXT("Choose Alloc first"));
  495.         return FALSE;
  496.         }
  497.  
  498.     return TRUE;
  499.     }
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506. /*
  507.  * App_FreeAllocations
  508.  *
  509.  * Purpose:
  510.  *  Centralized place to clean up allocations made on
  511.  *  the current IMalloc.
  512.  *
  513.  * Parameters:
  514.  *  pApp            PAPP identifying the object.
  515.  *  fRelease        BOOL indicating if we're to
  516.  *                  IMalloc::Release as well.
  517.  *
  518.  * Return Value:
  519.  *  None
  520.  */
  521.  
  522. void App_FreeAllocations(PAPP pApp, BOOL fRelease)
  523.     {
  524.     UINT    i;
  525.  
  526.     if (NULL==pApp->m_pIMalloc)
  527.         return;
  528.  
  529.     if (pApp->m_fAllocated)
  530.         {
  531.         for (i=0; i < CALLOCS; i++)
  532.             {
  533.             if (NULL!=pApp->m_rgpv[i])
  534.                 {
  535.                 pApp->m_pIMalloc->lpVtbl->Free(pApp->m_pIMalloc
  536.                     , pApp->m_rgpv[i]);
  537.                 }
  538.  
  539.             pApp->m_rgpv[i]=NULL;
  540.             }
  541.  
  542.         pApp->m_fAllocated=FALSE;
  543.         }
  544.  
  545.     if (fRelease)
  546.         {
  547.         pApp->m_pIMalloc->lpVtbl->Release(pApp->m_pIMalloc);
  548.         pApp->m_pIMalloc=NULL;
  549.         }
  550.  
  551.     return;
  552.     }
  553.  
  554.  
  555.  
  556.  
  557.  
  558. /*
  559.  * App_Message
  560.  *
  561.  * Purpose:
  562.  *  Displays a message in the client area of the window.  This is
  563.  *  just to centralize the call to simpify other code.
  564.  *
  565.  * Parameters:
  566.  *  pApp            PAPP identifying the object.
  567.  *  psz             LPTSTR to the string to display.
  568.  *
  569.  * Return Value:
  570.  *  None
  571.  */
  572.  
  573. void App_Message(PAPP pApp, LPTSTR psz)
  574.     {
  575.     HDC     hDC;
  576.     RECT    rc;
  577.  
  578.     hDC=GetDC(pApp->m_hWnd);
  579.     GetClientRect(pApp->m_hWnd, &rc);
  580.  
  581.     SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  582.     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  583.  
  584.     /*
  585.      * We'll just be sloppy and clear the whole window as
  586.      * well as write the string with one ExtTextOut call.
  587.      * No word wrapping here...
  588.      */
  589.  
  590.     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, psz, lstrlen(psz), NULL);
  591.     ReleaseDC(pApp->m_hWnd, hDC);
  592.     return;
  593.     }
  594.