File:  [OS/2 SDKs] / os232sdk / toolkt20 / c / samples / vmm / vmm_user.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:30 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1990, HEAD
Microsoft OS/2 SDK 2.0 05-30-1990

/*==================================================================*\
 *  Vmm_user.c - routines for handling messages not processed	    *
 *		by the standard message processing routine	    *
 *	Created 1990, Microsoft, IBM Corp.        	      		*
 *------------------------------------------------------------------*
 *								    *
 *  This module contains the code for processing messages sent	    *
 *  to the standard window that the standard window does not	    *
 *  process.  The application developer need only modify this	    *
 *  file in order to implement new menu items or process	    *
 *  messages not handled by the standard message routine.	    *
 *								    *
 *  This module also contains some routines that demonstate the     *
 *  various dialog box controls and message box types that can	    *
 *  be used.  The sample code should be deleted when this	    *
 *  module is modified for an application.  The demonstration	    *
 *  code is identified by comments.				    *
 *								    *
 *------------------------------------------------------------------*
 *								    *
 *  This source file contains the following functions:		    *
 *								    *
 *	UserWndProc(hwnd, msg, mp1, mp2) - user window procedure    *
 *	UserCommand(mp1, mp2) - user WM_COMMAND processor	    *
 *	VMM_Error(pszFunction, ulErrorCode) - Error processing	    *
 *	CleanUpArray(pvAddress) - Page table maintenance	    *
 *	StoreInArray(pvAddress, ulNumPages) - Page table maintenance*
 *								    *
\*==================================================================*/

/*------------------------------------------------------------------*\
 *  Include files, macros, defined constants, and externs	    *
\*------------------------------------------------------------------*/

#define  LINT_ARGS

#define  INCL_WIN
#define  INCL_DOSPROCESS
#define  INCL_DOSERRORS
#include <os2.h>
#include "stdio.h"
#include "vmm_main.h"
#include "vmm_dlg.h"
#include "vmm_xtrn.h"
#include "string.h"
extern ULONG clrBackground, clrForeground;

/*--------------------------------------------------------------*\
 *  Global variables						*
\*--------------------------------------------------------------*/

ULONG	    ulFreePage = 0L;		/* First free page entry in array */

PAGEENTRY   apgentry[MAXPAGES]; 	/* Application page table	  */

OBJSTRUCT   ObjAlloc;

char	    szBuffer[BUFF_SIZE];

MSGENTRY    amsgentry[] =
    {
	{ ERROR_INVALID_PARAMETER,
	  "%s\n\nInvalid Parameter",
	  MB_ICONASTERISK
	},

	{ ERROR_ACCESS_DENIED,
	  "%s\n\nAccess to Memory Denied",
	  MB_ICONASTERISK
	},

	{ ERROR_NOT_ENOUGH_MEMORY,
	  "%s\n\nInsufficient Memory",
	  MB_ICONASTERISK
	},

	{ ERROR_INVALID_ACCESS,
	  "%s\n\nAn Invalid access to memory was"
	  " attempted.",
	  MB_ICONASTERISK
	},

	{ ERROR_INVALID_ADDRESS,
	  "%s\n\nAddress Given is Invalid",
	  MB_ICONASTERISK
	},

	{ ERROR_INTERRUPT,
	  "%s\n\nThe call was interrupted by an external"
	  " event and was not completed. Please retry the"
	  " operation.",
	  MB_ICONASTERISK
	},

    /* Errors following are application defined */

	{ VMERR_MAX_ALLOCATED,
	  "%s\n\nThe allocation has surpassed"
	  " this application's maximum number of displayable"
	  " pages of %u. Each page contains 4096 bytes"
	  " of data.",
	  MB_ICONASTERISK
	},

	{ VMERR_ZERO_ALLOCATED,
	  "%s\n\nA minimum of 1 byte must be specified for"
	  " an allocation.",
	  MB_ICONASTERISK
	},

	{ VMERR_TILE_ONLY,
	  "%s\n\nAllocation attempted with"
	  " tiled attribute and no access"
	  " protection specifed. Access protection required to"
	  " properly allocate memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_COMMIT_AND_TILE_ONLY,
	  "%s\n\nAllocation attempted with no access"
	  " protection specified. Access protection required to"
	  " properly allocate memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_ALREADY_FREED,
	  "%s\n\nThe memory address specified to be"
	  " freed has not been allocated. Only previously"
	  " allocated memory may be freed.",
	  MB_ICONASTERISK
	},

	{ VMERR_NOT_BASEPAGE,
	  "%s\n\nThe memory address specified to be"
	  " freed is not a base-page address. Only"
	  " base pages"
	  " may be freed.",
	  MB_ICONASTERISK
	},

	{ VMERR_DECOMMIT_RESERVED,
	  "%s\n\nThe memory specified to be"
	  " decommitted is in a reserved"
	  " state. Memory must"
	  " be committed before it can be decommitted.",
	  MB_ICONASTERISK
	},

	{ VMERR_ACCESS_ON_RESERVED,
	  "%s\n\nAccess protection specified for"
	  " reserved memory. Access protection may "
	  " only be specified for committed memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_ACCESS_AND_DECOMMIT,
	  "%s\n\nAccess protection specified when"
	  " attempting to decommit memory. No access protection"
	  " may be specified when decommitting memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_COMMIT_ON_COMMITTED,
	  "%s\n\nCommit Memory specified for"
	  " previously"
	  " committed memory. Choose \"Default\" or \""
	  "Decommit\" for committed memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_COMMIT_ONLY,
	  "%s\n\nCommit Memory specified with"
	  " no access"
	  " protection specifed. Access protection required when"
	  " committing memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_SET_NO_PARMS,
	  "%s\n\nNo parameters specified. Parameters"
	  " must be specified when using %s.",
	  MB_ICONASTERISK
	},

	{ VMERR_SET_ZERO_SIZE,
	  "%s\n\nSetting allocation attributes and/or access protection"
	  " on zero bytes is not permitted."
	  " A minimum size of one byte must be specified to set"
	  " allocation attributes and/or access protection on memory.",
	  MB_ICONASTERISK
	},

	{ VMERR_SET_ON_FREE,
	  "%s\n\nSetting allocation attributes and/or access protection"
	  " on non-allocated memory is not"
	  " permitted. Memory must be allocated before allocation attributes"
	  " or access protection may be specified for it.",
	  MB_ICONASTERISK
	},

	{ VMERR_DEFAULT,
	  "%s\n\n Error #%u occured during the call.",
	  MB_ICONASTERISK
	}
    };

/*--------------------------------------------------------------*\
 *  Entry point declarations					*
\*--------------------------------------------------------------*/

VOID VMM_Error(PSZ pszFunction, ULONG ulErrorCode);

VOID CleanUpArray(PVOID pvAddress);

VOID StoreInArray(PVOID pvAddress, ULONG ulNumPages);

MRESULT EXPENTRY ReadMemDlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

MRESULT EXPENTRY WriteMemDlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

MRESULT EXPENTRY FreeMemDlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

MRESULT EXPENTRY SetMem1DlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

MRESULT EXPENTRY SetMem2DlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

MRESULT EXPENTRY AllocMemDlgProc(HWND hwnd, USHORT msg,
                                    MPARAM mp1, MPARAM mp2);

/****************************************************************\
 *  Non-standard window message processing routine		*
 *--------------------------------------------------------------*
 *								*
 *  Name:   UserWndProc(hwnd, msg, mp1, mp2)			*
 *								*
 *  Purpose: Process any messages sent to hwndMain that 	*
 *		are not processed by the standard window	*
 *		procedure					*
 *								*
 *  Usage:  Routine is called for each message MainWndProc	*
 *	    does not process					*
 *								*
 *  Method: A switch statement branches control based upon	*
 *	    the message passed.  Any messages not processed	*
 *	    here must be passed onto WinDefWindowProc() 	*
 *								*
 *  Returns: Return value depended upon the message processed	*
\****************************************************************/
MRESULT UserWndProc(hwnd, msg, mp1, mp2)
HWND hwnd;	/* handle of window */
USHORT msg;	/* id of message */
MPARAM mp1;	/* first message parameter */
MPARAM mp2;	/* second message parameter */
{

    switch(msg)  {

    /*--------------------------------------------------------------*\
     *	Add case statements for message ids you wish to process     *
    \*--------------------------------------------------------------*/

	default:    /* default must call WinDefWindowProc() */
	    return(WinDefWindowProc(hwnd, msg, mp1, mp2));
	    break;
    }

    return 0L;

}   /* UserWndProc() */

/****************************************************************\
 *  DOS API and Application Specific Error reporting routine	*
 *--------------------------------------------------------------*
 *								*
 *  Name:   VMM_Error(pszFunction, ulErrorCode) 		*
 *								*
 *  Purpose: Display errors returned by system calls to 	*
 *	     the user when they occur. All other error handling *
 *	     is done inside the functions themselves		*
 *								*
 *  Usage:  Routine is called for each error that the dialog	*
 *	    functions do not process				*
 *								*
 *  Method: A switch statement branches control based upon	*
 *	    the error number passed. Any message that comes	*
 *	    in that is not known is given a generic message.	*
 *	    The message is displayed with WinMessageBox 	*
 *								*
 *  Returns:							*
\****************************************************************/
VOID VMM_Error(pszFunction, ulErrorCode)
PSZ	pszFunction;
ULONG	ulErrorCode;
{
    char    szTempBuf[BUFF_SIZE];
    ULONG   ulMsgIndex;

    ulMsgIndex = 0L;

    while((amsgentry[ulMsgIndex].ulMsgNum != ulErrorCode) &&
	  (amsgentry[ulMsgIndex].ulMsgNum != VMERR_DEFAULT))
	ulMsgIndex++;

    strcpy(szTempBuf,amsgentry[ulMsgIndex].szMsgText);

    if (amsgentry[ulMsgIndex].ulMsgNum == VMERR_DEFAULT)
    {
	sprintf(szBuffer,szTempBuf,pszFunction,ulErrorCode);
    }
    else if (amsgentry[ulMsgIndex].ulMsgNum == VMERR_MAX_ALLOCATED)
    {
	sprintf(szBuffer,szTempBuf,pszFunction,MAXPAGES);
    }
    else if (amsgentry[ulMsgIndex].ulMsgNum == VMERR_SET_NO_PARMS)
    {
	sprintf(szBuffer,szTempBuf,pszFunction,pszFunction);
    }
    else
    {
	sprintf(szBuffer,szTempBuf,pszFunction);
    }

    WinMessageBox(HWND_DESKTOP,
		  hwndMain,
		  szBuffer,
		  szAppName,
		  0,
		  MB_OK | amsgentry[ulMsgIndex].usMsgIcon);

}

/****************************************************************\
 *  Procedure to remove freed pages from array			*
 *--------------------------------------------------------------*
 *								*
 *  Name:  CleanUpArray(pvAddress)				*
 *								*
 *  Purpose: Remove pages that the user indicated from the	*
 *	     array of pages stored				*
 *								*
 *  Usage:  Routine is called after each successful free	*
 *	    memory call issued by the user			*
 *								*
 *  Method: Pages are removed by finding the address in the	*
 *	    array that matches what the user input, and then	*
 *	    removing all subsequent pages until another base	*
 *	    page is found or the last stored page is reached	*
 *								*
 *  Returns:							*
\****************************************************************/
VOID CleanUpArray(pvAddress)
PVOID pvAddress;
{
ULONG	ulIndexLow;
ULONG	ulIndexHigh;

    /* At entry, we know that the pvAddress page is a base page and we
       need to free up the pages associated with the base page for the
       object. To do this, we find the next base address. We then make
       the copies. */

    ulIndexLow = 0;

    while((apgentry[ulIndexLow].pvAddress != pvAddress) &&
	  (ulIndexLow < ulFreePage))
	ulIndexLow++;

    /* If DosFreeMem worked but the address is not in our page array,
       then don't modify the array or the ulFreePage count. */

    if (ulIndexLow < ulFreePage)
    {
	apgentry[ulIndexLow].fBaseAddr = FALSE;

	ulIndexHigh = ulIndexLow + 1;

	while((apgentry[ulIndexHigh].fBaseAddr == FALSE) &&
	      (ulIndexHigh < ulFreePage))
	    ulIndexHigh++;

	while(ulIndexHigh < ulFreePage)
	    apgentry[ulIndexLow++] = apgentry[ulIndexHigh++];

	ulFreePage -= (ulIndexHigh-ulIndexLow);
    }
}

/****************************************************************\
 *  Procedure to store allocated pages in array 		*
 *--------------------------------------------------------------*
 *								*
 *  Name:  StoreInArray(pvAddress,ulNumPages)			*
 *								*
 *  Purpose: Store pages that were just successfully allocated	*
 *	     in our array so we can track them			*
 *								*
 *  Usage:  Routine is called after each successful allocation	*
 *	    of memory by the user				*
 *								*
 *  Method: The pages are added to the end of the array based	*
 *	    upon the current status of our global end of array	*
 *	    index variable (ulFreePage) 			*
 *								*
 *  Returns:							*
\****************************************************************/
VOID StoreInArray(pvAddress,ulNumPages)
PVOID	pvAddress;
ULONG	ulNumPages;
{
ULONG	temp;

    /* Set all base indicators for the new pages to FALSE, and set the
       addresses for the pages. */

    for(temp = 0L; temp < ulNumPages; temp++)
    {
	apgentry[temp+ulFreePage].pvAddress = (PVOID)((ULONG)pvAddress +
					      (PAGESIZE * temp));
	apgentry[temp+ulFreePage].fBaseAddr = FALSE;
    }

    /* Set the base indicator of the first page in the object to be
       TRUE */

    apgentry[ulFreePage].fBaseAddr = TRUE;

    ulFreePage += ulNumPages;
}

/****************************************************************\
 *  Non-standard menu item command processing procedure 	*
 *--------------------------------------------------------------*
 *								*
 *  Name:   UserCommand(mp1, mp2)				*
 *								*
 *  Purpose: Process any WM_COMMAND messages send to hwndMain	*
 *		that are not processed by MainCommand		*
 *								*
 *  Usage:  Routine is called for each WM_COMMAND that is	*
 *	    not posted by a standard menu item			*
 *								*
 *  Method: A switch statement branches control based upon	*
 *	    the id of the control which posted the message	*
 *								*
 *  Returns:							*
\****************************************************************/
VOID UserCommand(mp1, mp2)
MPARAM mp1;	/* first message parameter */
MPARAM mp2;	/* second message parameter */
{
PVOID	pvMemAddress;
ULONG	ulRegionSize;

ULONG	ulTempRegionSize;
ULONG	flTempAttributes;

ULONG	ulPages;	/* Number of pages requested by user */
ULONG	rc;		/* Return Code variable from calls  */
ULONG	rc2;		/* Return Code variable for investigative calls */

    switch(SHORT1FROMMP(mp1))
    {

    /*--------------------------------------------------------------*\
     *	Add case statements for menuitem ids you wish to process    *
    \*--------------------------------------------------------------*/

	case IDM_VMMALLOC:
            ObjAlloc.ulSize = 5000;     /* default size to allocate */
            ObjAlloc.ulAttr = PAG_READ | PAG_WRITE | PAG_EXECUTE;

	    if(WinDlgBox( HWND_DESKTOP,
                        hwndMain,
                        (PFNWP) AllocMemDlgProc,
                        NULL,
                        (ULONG) IDD_ALLOCMEM,
                        (PVOID) &ObjAlloc ))

	    {
		/* Figure out the number of pages requested. */

                ulPages = (ObjAlloc.ulSize / PAGESIZE);
                if ((ObjAlloc.ulSize % PAGESIZE) != 0L)
		{
		    ulPages++;
		}

		/* If the number of pages requested is zero (zero
		   bytes specified), or the number of pages is greater
		   than the number left in the array, report the error
		   condition. Otherwise, make the DosAllocMem call and
		   set any error condition returned by the call. */

		if (ulPages == 0L)
		{
		    rc = VMERR_ZERO_ALLOCATED;
		}
		else if (ulPages + ulFreePage > MAXPAGES + 1)
		{
		    rc = VMERR_MAX_ALLOCATED;
		}
		else
		{
		    rc = DosAllocMem(&pvMemAddress,
                                     ObjAlloc.ulSize,
                                     ObjAlloc.ulAttr);
		}
		/* If an error has occured, display it. Otherwise,
		   process the request. */

		if (rc != 0L)
		{
                    if (ObjAlloc.ulAttr == 0L)
		    {
			rc = VMERR_SET_NO_PARMS;
		    }
                    else if (ObjAlloc.ulAttr == PAG_COMMIT)
		    {
			rc = VMERR_COMMIT_ONLY;
		    }
                    else if (ObjAlloc.ulAttr == (PAG_COMMIT | OBJ_TILE))
		    {
			rc = VMERR_COMMIT_AND_TILE_ONLY;
		    }
                    else if (ObjAlloc.ulAttr == OBJ_TILE)
		    {
			rc = VMERR_TILE_ONLY;
		    }
		    VMM_Error("DosAllocMem()",rc);
		}
		else
		{
		    StoreInArray(pvMemAddress,ulPages);
		    WinInvalidateRect(hwndMain, NULL, TRUE);
		}
	    }
	    break;

	case IDM_VMMFREE:

            if (WinDlgBox(HWND_DESKTOP,
                      hwndMain,
                      (PFNWP) FreeMemDlgProc,
                      NULL,
                      (ULONG) IDD_FREEMEM,
                      (PVOID) &ObjAlloc ) != 0)
	    {

                rc = DosFreeMem(ObjAlloc.pvAddress);

		if (rc != 0L)
		{
		    ulRegionSize = 1L;

		    /* Try to figure out why the error occured based
		       on actual page attributes of page requested to be
		       freed. */

                    rc2 = DosQueryMem(ObjAlloc.pvAddress,
				      &ulTempRegionSize,
				      &flTempAttributes);

		    if (rc2 == 0L)

		    /* If the page requested to be freed was already
		       in the freed state, or the requested page in the
		       object to be freed is not the base page of the
		       object, set the appropriate error condition. */

		    {
			if ((flTempAttributes & PAG_FREE) != 0L)
			{
			    rc = VMERR_ALREADY_FREED;
			}
			else if ((flTempAttributes & PAG_BASE) == 0L)
			{
			    rc = VMERR_NOT_BASEPAGE;
			}
		    }

		    VMM_Error("DosFreeMem()",rc);
		}
		else
		{
                    CleanUpArray(ObjAlloc.pvAddress);
		    WinInvalidateRect(hwndMain, NULL, TRUE);
		}
	    }
	    break;

	case IDM_VMMSET:

            if (WinDlgBox(HWND_DESKTOP,
                      hwndMain,
                      (PFNWP) SetMem1DlgProc,
		      NULL,
                      (ULONG) IDD_SETMEM1,
                      (PVOID) &ObjAlloc ))
	    {
                if (WinDlgBox(HWND_DESKTOP,
                          hwndMain,
                          (PFNWP) SetMem2DlgProc,
                          NULL,
                          (ULONG) IDD_SETMEM2,
                          (PVOID) &ObjAlloc ))
		{
                    rc = DosSetMem(ObjAlloc.pvAddress,
                                   ObjAlloc.ulSize,
                                   ObjAlloc.ulAttr);

		    /* If an error occured making the DosSetMem call,
		       try to figure out the cause of the error by
		       studying the requested access and the access on
		       the memory prior to the DosSetMem call. */

		    if (rc != 0L)
		    {
			ulTempRegionSize = 1L;

                        rc2 = DosQueryMem(ObjAlloc.pvAddress,
					  &ulTempRegionSize,
					  &flTempAttributes);

			if (rc2 == 0L)
			{

			    /* If no attributes, commit with no other
			       attributes, or a size of zero was
			       specified, set the appropriate error
			       condition. */

                            if (ObjAlloc.ulAttr == 0L)
			    {
				rc = VMERR_SET_NO_PARMS;
			    }
                            else if (ObjAlloc.ulAttr == PAG_COMMIT)
			    {
				rc = VMERR_COMMIT_ONLY;
			    }
                            else if (ObjAlloc.ulSize == 0L)
			    {
				rc = VMERR_SET_ZERO_SIZE;
			    }

			    /* If memory is not allocated then set
			       error condition. */

                            else if ((ObjAlloc.ulAttr & PAG_FREE) != 0L)
			    {
				rc = VMERR_SET_ON_FREE;
			    }

			    /* If the memory was already in the
			       reserved state and the user attempted to
			       decommit it or set attributes for it, set
			       the error condition. */

			    else if ((flTempAttributes & PAG_COMMIT) == 0L)
			    {
                                if ((ObjAlloc.ulAttr & PAG_DECOMMIT) != 0L)
				{
				    rc = VMERR_DECOMMIT_RESERVED;
				}
                                else if ((ObjAlloc.ulAttr & ~PAG_COMMIT) != 0L)
				{
				    rc = VMERR_ACCESS_ON_RESERVED;
				}
			    }

			    /* If the memory was in a committed state
			       and the user attempted to decommit it and
			       set attributes, or the user attempts to
			       commit the memory, set the appropriate
			       error condition. */

			    else
			    {
                                if (((ObjAlloc.ulAttr &  PAG_DECOMMIT) != 0L)
                                  && ((ObjAlloc.ulAttr & ~PAG_DECOMMIT) != 0L))
				{
				    rc = VMERR_ACCESS_AND_DECOMMIT;
				}

                                else if ((ObjAlloc.ulAttr & PAG_COMMIT) != 0L)
				{
				    rc = VMERR_COMMIT_ON_COMMITTED;
				}
			    }

			}

                        VMM_Error("DosSetMem()",rc);
		    }
		    else
		    {
                        WinInvalidateRect(hwndMain, NULL, TRUE);
		    }
		}
	    }
	    break;

	case IDM_VMMWRITE:

            if (WinDlgBox(HWND_DESKTOP,
                            hwndMain,
                            (PFNWP) WriteMemDlgProc,
                            NULL,
                            (ULONG) IDD_WRITEMEM,
                            (PVOID) NULL))
	    {

                WinInvalidateRect(hwndMain, NULL, TRUE);
	    }

	    break;


        case IDM_VMMREAD:

            if (WinDlgBox(HWND_DESKTOP,
                            hwndMain,
                            (PFNWP) ReadMemDlgProc,
                            NULL,
                            (ULONG) IDD_READMEM,
                            (PVOID) &ObjAlloc ))
	    {
                sprintf(szBuffer, "Address %p contains %s",
                        ObjAlloc.pvAddress, ObjAlloc.pvAddress);

                WinMessageBox(HWND_DESKTOP,
                                hwndMain,
                                szBuffer,
                                "Read Memory",
                                0,
                                MB_OK);

                WinInvalidateRect(hwndMain, NULL, TRUE);
	    }

	    break;

	default:
	    break;
    }

    /* This routine currently doesn't use the mp2 parameter but       *\
     *	it is referenced here to prevent an 'Unreferenced Parameter'  *
    \*	warning at compile time.				      */
    mp2;

}   /* UserCommand() */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.