home *** CD-ROM | disk | FTP | other *** search
- /*static char *SCCSID = "@(#)vmm_user.c 6.11 92/02/19";*/
- /*==================================================================*\
- * VMM_USER.C - routines for handling messages not processed *
- * by the standard message processing routine *
- * (C) Copyright IBM Corporation 1992 *
- *------------------------------------------------------------------*
- * *
- * 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: *
- * *
- * 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 *
- \*------------------------------------------------------------------*/
- #include "vmm.h"
-
- /*--------------------------------------------------------------*\
- * Global variables *
- \*--------------------------------------------------------------*/
- 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
- }
- };
-
- /****************************************************************\
- * 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 *
- * *
- \****************************************************************/
- VOID VMM_Error(PSZ pszFunction, ULONG ulErrorCode)
- {
- CHAR szTempBuf[BUFF_SIZE];
- ULONG ulMsgIndex;
-
- ulMsgIndex = 0L;
- /* Serach error message */
- 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);
- }
- WinAlarm(HWND_DESKTOP, WA_ERROR);
- WinMessageBox(HWND_DESKTOP,
- hwndMain,
- szBuffer,
- szAppName,
- 0,
- MB_OK | MB_MOVEABLE | amsgentry[ulMsgIndex].usMsgIcon);
- return;
- }
-
- /****************************************************************\
- * 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 *
- * *
- \****************************************************************/
- VOID CleanUpArray(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;
- /* Look for the pointed page */
- while((apgentry[ulIndexLow].pvAddress != pvAddress) &&
- (ulIndexLow < ulFreePage))
- ulIndexLow++;
-
- if (ulIndexLow < ulFreePage)
- {
- apgentry[ulIndexLow].fBaseAddr = FALSE;
- ulIndexHigh = ulIndexLow + 1;
- /* Look for the next base page */
- while((apgentry[ulIndexHigh].fBaseAddr == FALSE) &&
- (ulIndexHigh < ulFreePage))
- ulIndexHigh++;
-
- while(ulIndexHigh < ulFreePage)
- apgentry[ulIndexLow++] = apgentry[ulIndexHigh++];
-
- ulFreePage -= (ulIndexHigh-ulIndexLow);/* Reset the starting page */
- MessageBox(HWND_DESKTOP, IDMSG_SUCCESSFREE, "Note !", MB_OK, FALSE);
- }
- /* If DosFreeMem worked but the address is not in our page
- array, then don't modify the array or the ulFreePage count. */
-
- if (!ulFreePage) /* No memory is allocated */
- {
- EnableMenuItem(hwndMain,IDM_VMMFREE,FALSE);
- EnableMenuItem(hwndMain,IDM_VMMSET,FALSE);
- EnableMenuItem(hwndMain,IDM_VMMWRITE,FALSE);
- EnableMenuItem(hwndMain,IDM_VMMREAD,FALSE);
- }
- return;
- }
-
- /****************************************************************\
- * 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 *
- * *
- \****************************************************************/
- VOID StoreInArray(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; /* Move to new starting of free page */
-
- EnableMenuItem(hwndMain,IDM_VMMFREE,TRUE);
- EnableMenuItem(hwndMain,IDM_VMMSET,TRUE);
- EnableMenuItem(hwndMain,IDM_VMMWRITE,TRUE);
- EnableMenuItem(hwndMain,IDM_VMMREAD,TRUE);
- return;
- }
-
- /****************************************************************\
- * 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(MPARAM mp1, MPARAM mp2)
- {
- PVOID pvMemAddress=0L;
-
- ULONG ulTempRegionSize;
- ULONG flTempAttributes=0L;
-
- 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 = 4; /* Default size 4 k to allocate */
- ObjAlloc.ulAttr = /* Default attrib */
- PAG_READ | PAG_WRITE | PAG_EXECUTE;
- ObjAlloc.pvAddress = '\000';
-
- if(WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) AllocMemDlgProc,
- (HMODULE)0,
- (ULONG) IDD_ALLOCMEM,
- (PVOID) &ObjAlloc) )
- {
- /* Figure out the number of pages requested. */
- ulPages = (ObjAlloc.ulSize / PAGESIZE);
- if ((ObjAlloc.ulSize % PAGESIZE) != 0L)
- ulPages++; /* One more page */
-
- /* 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:
-
- ObjAlloc.pvAddress = '\000';
- if (WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) FreeMemDlgProc,
- (HMODULE)0,
- (ULONG) IDD_FREEMEM,
- (PVOID) &ObjAlloc ) != 0)
- {
- rc = DosFreeMem(ObjAlloc.pvAddress);
-
- if (rc != 0L)
- { /* DosFreeMem is fail */
- /* 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:
-
- ObjAlloc.pvAddress = '\000';
- if (WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) SetMem1DlgProc,
- (HMODULE)0,
- (ULONG) IDD_SETMEM1,
- (PVOID) &ObjAlloc ))
- {
- if (WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) SetMem2DlgProc,
- (HMODULE)0,
- (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)
- {
- rc = 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:
-
- ObjAlloc.pvAddress = '\000';
- if (WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) WriteMemDlgProc,
- (HMODULE)0,
- (ULONG) IDD_WRITEMEM,
- (PVOID) NULL))
-
- WinInvalidateRect(hwndMain, NULL, TRUE);
- break;
-
- case IDM_VMMREAD:
-
- ObjAlloc.pvAddress = '\000';
- if (WinDlgBox(HWND_DESKTOP,
- hwndMain,
- (PFNWP) ReadMemDlgProc,
- (HMODULE)0,
- (ULONG) IDD_READMEM,
- (PVOID) &ObjAlloc ))
- {
- if ( *( (CHAR *)(ObjAlloc.pvAddress) )== 0L )
- {
- sprintf(szBuffer, "Address %p doesn't contain data.",
- ObjAlloc.pvAddress);
- memset(ObjAlloc.pvAddress,0,sizeof(ObjAlloc.pvAddress));
- } else {
- sprintf(szBuffer, "Address %p contains\n %s",
- ObjAlloc.pvAddress, ObjAlloc.pvAddress);
- }
- WinMessageBox(HWND_DESKTOP,
- hwndMain,
- szBuffer,
- "Read Memory",
- 0,
- MB_INFORMATION| MB_OK | MB_MOVEABLE);
-
- 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. */
- return;
- } /* UserCommand() */
-