/***************************************************************************
 *                                                                         *
 *   ISGOODPT.C                                                            *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the GCOMM.LIB routine for determining if a pointer is         *
 *   valid.                                                                *
 *                                                                         *
 *                                            - R. Stein 2/12/93           *
 *                                            - Ilya Minkin 01/24/96       *
 *                                                                         *
 ***************************************************************************/
#ifdef GCWINNT
#include <windows.h>
#endif // GCWINNT
#include "gcomm.h"

#define FILREV "$Revision: 6 $"

#ifdef GCDOSP
DESC gpdesc;                       /* protection attribute storage         */
#endif // GCDOSP

CHAR *pinstd;                      /* validated pointer to use             */
                                   /* pinstd == prt if ptr is valid, points*/
                                   /* to an error message otherwise        */
#ifdef GCWINNT
static UINT qryBlockSize(const VOID *ptr);
#endif

UINT                               /*   return # of accessable bytes       */
goodblk(                           /* is blk of memory addressable w/o GP? */
const VOID *ptr,                   /*   pointer to block of bytes          */
UINT nbytes)                       /*   number of bytes to check           */
{
#ifdef GCDOS
#ifdef GCDOSP
     UINT n;
#endif // GCDOSP

     if (!goodptr(ptr)) {
          nbytes=0;
     }
#ifdef GCDOSP
     else {
          n=(UINT)gpdesc.size-FP_OFF(ptr);
          if (n < nbytes) {
               nbytes=n;
               pinstd="<incomplete block>";
          }
     }
#endif // GCDOSP
     return(nbytes);
#else
     UINT memBlockSize;

     if (ptr == NULL) {
          pinstd="<null pointer>";
          return(0);
     }
     memBlockSize=qryBlockSize(ptr);
     if (memBlockSize == 0) {
          pinstd="<invalid pointer>";
          return(0);
     }
     if (memBlockSize < nbytes) {
          nbytes=memBlockSize;
          pinstd="<incomplete block>";
     }
     return(nbytes);
#endif // GCDOS
}

GBOOL                              /*   return TRUE if stg pointer is valid*/
goodstg(                           /* validate string pointer              */
const CHAR *ptr)                   /*   pointer to validate                */
{
#ifdef GCDOS
     GBOOL retval;
#ifdef GCDOSP
     UINT n;
#endif // GCDOSP

     retval=goodptr(ptr);
#ifdef GCDOSP
     if (retval) {
          n=(UINT)gpdesc.size-FP_OFF(ptr);
          while (*ptr != '\0') {
               if (--n == 0) {
                    pinstd="<invalid string>";
                    return(FALSE);
               }
               ptr++;
          }
     }
#endif // GCDOSP
     return(retval);
#else
     if (IsBadStringPtr(ptr,0xFFFF)) {
          pinstd="<invalid string>";
          return(FALSE);
     }
     pinstd=(CHAR *)ptr;
     return(TRUE);
#endif // GCDOS
}

GBOOL                              /*   return TRUE if pointer is valid    */
goodcptr(                          /* validate function pointer            */
const VOID *ptr)                   /*   pointer to validate                */
{
     if (ptr == NULL) {
          pinstd="<null pointer>";
          return(FALSE);
     }
#ifdef GCDOS
#ifdef GCDOSP
     if ((FP_SEG(ptr)&7) != 7
      || DosGetSegDesc(FP_SEG(ptr),&gpdesc) != 0
      || FP_OFF(ptr) >= gpdesc.size
      || gpdesc.attrib == DATA16
      || gpdesc.attrib == DATA16_NOWRITE) {
          pinstd="<invalid pointer>";
          return(FALSE);
     }
#endif // GCDOSP
#else
     if (IsBadCodePtr((FARPROC)ptr)) {
          pinstd="<invalid pointer>";
          return(FALSE);
     }
     pinstd=(CHAR *)ptr;
#endif // GCDOS
     return(TRUE);
}

GBOOL                              /*   return TRUE if pointer is valid    */
goodptr(                           /* validate pointer                     */
const VOID *ptr)                   /*   pointer to validate                */
{
     if (ptr == NULL) {
          pinstd="<null pointer>";
          return(FALSE);
     }
#ifdef GCDOS
#ifdef GCDOSP
     if ((FP_SEG(ptr)&7) != 7
      || DosGetSegDesc(FP_SEG(ptr),&gpdesc) != 0
      || FP_OFF(ptr) >= gpdesc.size
      || gpdesc.attrib == CODE16_NOREAD) {
          pinstd="<invalid pointer>";
          return(FALSE);
     }
#endif // GCDOSP
#else
     /* This check validate R/W access to the first byte ptr points to     */
     if (IsBadReadPtr(ptr,1) || IsBadWritePtr(ptr,1)) {
          pinstd="<invalid pointer>";
          return(FALSE);
     }
#endif // GCDOS
     pinstd=(CHAR *)ptr;
     return(TRUE);
}

#ifdef GCWINNT
static UINT                        //   size of memory block with read/write acc
qryBlockSize(                      // get block size with read/write accesss
const VOID *ptr)                   //   block pointer
{
     MEMORY_BASIC_INFORMATION memInfo;
     DWORD size;

     VirtualQuery(ptr,&memInfo,sizeof(memInfo));
     if (memInfo.State != MEM_COMMIT
      || (memInfo.Protect&PAGE_READWRITE) != PAGE_READWRITE) {
          return(0);
     }
     else {
          size=(DWORD)ptr-(DWORD)memInfo.BaseAddress;
          return((UINT)(memInfo.RegionSize-size));
     }
}
#endif
